所有人:
最近我尝试利用cuda 5.5的最新特性来编程,即动态并行。但我有一个非常困惑的问题。我的代码在这里:
/* Includes, system */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
using namespace std;
/* Includes, cuda */
#include <cuda_runtime.h>
#include <cublas_v2.h>
/* Includes, cuda helper functions */
#include <helper_cuda.h>
#include "kernels.cu"
/* Matrix size */
#define N (275)
#define LengthSignal (64)
#define AmountSignal (255025)
#define NBLOCKX (32768)
#define NTHREADS_PER_BLOCK (128)
/* Declaration of the function that computes sgemm using CUBLAS device API */
__global__ void invokeDeviceCublasSgemm(float *d_A, float *Test);
/* Main */
int main(int argc, char **argv)
{
float *h_A;
float *d_A = 0;
int n2 = N * N;
h_A = (float *)malloc(n2 * sizeof(h_A[0]));
/* Fill the matrices with test data */
for (int i = 0; i < n2; i++)
{
h_A[i] = rand() / (float)RAND_MAX;
}
cudaMalloc((void **)&d_A, n2 * sizeof(h_A[0]));
/* Initialize the device matrices with the host matrices */
// cudaMemcpy(d_A, h_A, sizeof(float) * LengthSignal * AmountSignal, cudaMemcpyHostToDevice);
cudaMemcpy(d_A, h_A, n2 * sizeof(h_A[0]), cudaMemcpyHostToDevice);
int Length = 100;
float *h_Test = (float *) malloc(sizeof(float) * Length);
float *d_Test;
cudaMalloc((void **) &d_Test, sizeof(float) * Length);
cudaMemset(d_Test, 0, sizeof(float) * Length);
invokeDeviceCublasSgemm<<<NBLOCKX, NTHREADS_PER_BLOCK>>>(d_A, d_Test);
cudaMemcpy(h_Test, d_Test, sizeof(float) * Length, cudaMemcpyDeviceToHost);
printf("\n The first 10 elements of d_A in location 1 are: \n");
for (int j = 0; j < 10; j ++)
{
printf("%f ", h_Test[j]);
}
printf("\n The first 10 elements of d_A in location 2 are: \n");
for (int j = 10; j < 20; j ++)
{
printf("%f ", h_Test[j]);
}
printf("\n");
free(h_Test);
cudaFree(d_Test);
/* Memory clean up */
free(h_A);
cudaFree(d_A);
}
#ifndef __GLOBAL__CU__
#define __GLOBAL__CU__
__global__ void invokeDeviceCublasSgemm(float *d_A, float *Test)
{
// save the first 10 elements of d_A in location 1
for (int j = 0; j < 10; j ++)
{
Test[j] = d_A[j];
}
cublasHandle_t cnpHandle;
cublasCreate(&cnpHandle);
// save the first 10 elements of d_A in location 2
for (int j = 10; j < 20; j ++)
{
Test[j] = d_A[j - 10];
}
cublasDestroy(cnpHandle);
}
#endif
如果我将配置参数设置为<<>>,一切正常。结果是这样的:
位置1中的d_A的前10个元素是:
0.840188 0.394383 0.783099 0.798440 0.911647 0.197551 0.335223 0.768230 0.277775 0.553970
位置2中dúA的前10个元素是:
0.840188 0.394383 0.783099 0.798440 0.911647 0.197551 0.335223 0.768230 0.277775 0.553970
但是,如果我将配置参数设置为<>,则输出相当奇怪。结果是这样的:
位置1中的d_A的前10个元素是:
-0.0000000.0000000.0000000.0000000.0000000.0000000.0000000.0000000.0000000.0000000.000000
位置2中dúA的前10个元素是:
0.0000000.0000000.0000000.0000000.0000000.0000000.0000000.0000000.0000000.0000000.000000
我真的不知道为什么!我的代码只是来自“示例”的一点变化。
然后我删除最后一个代码“cublasDestroy(cnpHandle);”,然后它就正常了。结果是:
位置1中的d_A的前10个元素是:
0.840188 0.394383 0.783099 0.798440 0.911647 0.197551 0.335223 0.768230 0.277775 0.553970
位置2中dúA的前10个元素是:
0.840188 0.394383 0.783099 0.798440 0.911647 0.197551 0.335223 0.768230 0.277775 0.553970
有人有同样的问题吗?
谢谢!
最佳答案
做一些proper cuda error checking可以在主机API调用、设备API调用和cublasapi调用(以及内核调用)上做。如果不确定,请阅读动态并行性documentation。
很可能你在任何时候都exceeding the number of kernel launches that can be outstanding。有一个(可配置的)2048内核启动的限制,可以是未完成的。由于您的代码在主机内核启动参数为<<<32768, 128>>>
时失败,这意味着您正在尝试启动32768x128个线程,每个线程都可能尝试启动一个子内核。如果内核启动次数超过限制,则剩余的内核启动将失败。
“但我不会推出任何儿童食品??“实际上,使用设备CUBLAS API意味着内核可能会被启动。这就是CUBLAS系统的工作原理。
为了真正弄清楚,我再次强烈建议您进行可靠的错误检查。