此代码可以正常工作:
#include <stdio.h>
#define N 1000 // <-- Works for values < 2^16
__global__
void add(int *a, int *b) {
int i = blockIdx.x;
if (i<N) {
b[i] = 2*a[i];
}
}
int main() {
int max_value[2];
int ha[N], hb[N];
int *da, *db;
cudaMalloc((void **)&da, N*sizeof(int));
cudaMalloc((void **)&db, N*sizeof(int));
for (int i = 0; i<N; ++i) {
ha[i] = i;
}
cudaMemcpy(da, ha, N*sizeof(int), cudaMemcpyHostToDevice);
add<<<N, 1>>>(da, db);
cudaMemcpy(hb, db, N*sizeof(int), cudaMemcpyDeviceToHost);
max_value[0] = hb[0];
int i;
for (i = 0; i < N; i++) {
if (hb[i] > max_value[0]) {
max_value[0] = hb[i];
max_value[1] = i;
}
}
cudaFree(da);
cudaFree(db);
printf("Max number %d, from value:%d \n", max_value[0], max_value[1]);
getchar();
return 0;
}
但当我将数字N
(数组中的项目)从1000更改为&gt;(2 16 ) - 1 时程序崩溃。< / p>
我认为这是主机上的溢出,所以我将ha
和hb
的数组声明移至BSS segment
并将N
更改为100万。
#include <stdio.h>
#define N 1000000 // <----
__global__
void add(int *a, int *b) {
int i = blockIdx.x;
if (i<N) {
b[i] = 2*a[i];
}
}
static int ha[N]; // <----
static int hb[N]; // <----
int main() {
int max_value[2];
// int ha[N], hb[N];
int *da, *db;
cudaMalloc((void **)&da, N*sizeof(int));
cudaMalloc((void **)&db, N*sizeof(int));
for (int i = 0; i<N; ++i) {
ha[i] = i;
}
cudaMemcpy(da, ha, N*sizeof(int), cudaMemcpyHostToDevice);
add<<<N, 1>>>(da, db);
cudaMemcpy(hb, db, N*sizeof(int), cudaMemcpyDeviceToHost);
max_value[0] = hb[0];
int i;
for (i = 0; i < N; i++) {
if (hb[i] > max_value[0]) {
max_value[0] = hb[i];
max_value[1] = i;
}
}
cudaFree(da);
cudaFree(db);
printf("Max number %d, from value:%d \n", max_value[0], max_value[1]);
getchar();
return 0;
}
现在我没有收到错误,但hb
数组为空。
我的代码有什么问题?
如何将大数组分配给设备并获得有效结果?
更新:我已插入错误检查代码,我得到的错误是 - &gt; &#34;无效的配置参数&#34; 。
更新的代码是:
#include <stdio.h>
#include <time.h>
#include <math.h>
#include <thrust/system_error.h>
#include <thrust/system/cuda/error.h>
#include <sstream>
const int N = 70000;
#define checkCudaErrors(error) {\
if (error != cudaSuccess) {\
printf("CUDA Error - %s:%d: '%s'\n",__FILE__,__LINE__,cudaGetErrorString(error));\
exit(1);\
}\
}\
__global__
void add(int *a, int *b) {
int i = blockIdx.x;
if (i<N) {
b[i] = 2*a[i];
}
}
static int ha[N];
static int hb[N];
int main() {
// int ha[N], hb[N];
int max_value[2];
int deviceCount = 0;
cudaGetDeviceCount(&deviceCount);
cudaError_t err=cudaDeviceReset();
if(err!=cudaSuccess){printf("%s in %s at line %d\n",cudaGetErrorString(err),__FILE__,__LINE__);}
printf("Device count: %d \n", deviceCount);
for (int i = 0; i<N; ++i) { ha[i] = i; }
int *da, *db;
checkCudaErrors(cudaMalloc((void **)&da, N*sizeof(int)));
checkCudaErrors(cudaMalloc((void **)&db, N*sizeof(int)));
checkCudaErrors(cudaMemcpy(da, ha, N*sizeof(int), cudaMemcpyHostToDevice));
add<<<N, 1>>>(da, db); // <--- Invalid configuration error
checkCudaErrors(cudaMemcpy(hb, db, N*sizeof(int), cudaMemcpyDeviceToHost));
max_value[0] = hb[0];
int i;
for (i = 0; i < N; i++) {
if (hb[i] > max_value[0]) {
max_value[0] = hb[i];
max_value[1] = i;
}
}
cudaError_t error = cudaGetLastError();
if(error != cudaSuccess) {
printf("CUDA error: %s\n", cudaGetErrorString(error));
getchar();
exit(-1);
}
getchar();
return 0;
}
该设备是GeForce GTX 470,我正在使用
进行编译 nvcc -o foo new.cu
答案 0 :(得分:5)
您的设备(GTX 470)是cc2.0设备(计算能力)。
无效配置参数错误是由于以下事实:对于cc2.0设备,1-D网格的块数限制为65535.此信息可在programming guide中找到(&#34 ;线程块网格的最大x维度&#34;)或运行deviceQuery
CUDA示例代码。所以你在这里N
的选择太大了:
add<<<N, 1>>>(da, db);
^
使用cc2.0设备的常用解决方法是创建一个多维的线程块网格,这允许更多的线程块。内核启动参数实际上可以是dim3
个变量,它们允许指定多维网格(线程块)或多维线程块(线程)。
要正确执行此操作,您还需要更改内核代码,以便从可用的多维变量中创建正确的全局唯一线程ID。
以下工作示例给出了一组可能的最小变化来演示这个概念,并且似乎正确地为我运行:
$ cat t363.cu
#include <stdio.h>
#include <time.h>
#include <math.h>
#include <thrust/system_error.h>
#include <thrust/system/cuda/error.h>
#include <sstream>
const int N = 70000;
#define checkCudaErrors(error) {\
if (error != cudaSuccess) {\
printf("CUDA Error - %s:%d: '%s'\n",__FILE__,__LINE__,cudaGetErrorString(error));\
exit(1);\
}\
}\
__global__
void add(int *a, int *b) {
int i = blockIdx.x + blockIdx.y*gridDim.x;
if (i<N) {
b[i] = 2*a[i];
}
}
static int ha[N];
static int hb[N];
int main() {
int max_value[2];
int deviceCount = 0;
cudaGetDeviceCount(&deviceCount);
cudaError_t err=cudaDeviceReset();
if(err!=cudaSuccess){printf("%s in %s at line %d\n",cudaGetErrorString(err),__FILE__,__LINE__);}
printf("Device count: %d \n", deviceCount);
for (int i = 0; i<N; ++i) { ha[i] = i; }
int *da, *db;
checkCudaErrors(cudaMalloc((void **)&da, N*sizeof(int)));
checkCudaErrors(cudaMalloc((void **)&db, N*sizeof(int)));
checkCudaErrors(cudaMemcpy(da, ha, N*sizeof(int), cudaMemcpyHostToDevice));
dim3 mygrid(N/10, 10);
add<<<mygrid, 1>>>(da, db);
checkCudaErrors(cudaMemcpy(hb, db, N*sizeof(int), cudaMemcpyDeviceToHost));
max_value[0] = hb[0];
int i;
for (i = 0; i < N; i++) {
if (hb[i] > max_value[0]) {
max_value[0] = hb[i];
max_value[1] = i;
}
}
printf("max_value[0] = %d, max_value[1] = %d\n", max_value[0], max_value[1]);
cudaError_t error = cudaGetLastError();
if(error != cudaSuccess) {
printf("CUDA error: %s\n", cudaGetErrorString(error));
getchar();
exit(-1);
}
return 0;
}
$ nvcc -arch=sm_20 -o t363 t363.cu
nvcc warning : The 'compute_20', 'sm_20', and 'sm_21' architectures are deprecated, and may be removed in a future release (Use -Wno-deprecated-gpu-targets to suppress warning).
$ ./t363
Device count: 4
max_value[0] = 139998, max_value[1] = 69999
$
注意:
如果您在cc3.0或更高版本的设备上运行原始代码,则不应抛出该错误。较新的CUDA设备将1D网格限制提高到2 ^ 31-1。但是如果你想要超过这个数量的块(大约2B)那么你将不得不再去一个多维网格。
在CUDA 8中不推荐使用cc2.0设备,并且即将推出的CUDA 9版本正在删除对它们的支持。