【发布时间】:2014-01-16 06:52:15
【问题描述】:
我已经使用 Cuda 实现了各种算法,例如矩阵乘法、Cholesky 分解和下三角矩阵的求逆(通过前向替换)。
对于其中一些算法,我在内核中有一个 for 循环,它会多次重复部分内核代码。这一切都适用于(扁平化:由一维数组表示)矩阵(浮点数)高达约 200x200,for 循环调用内核代码的一部分 200 次。将矩阵大小增加到 1000x1000(使用 for 循环调用内核代码的部分 1000 次)会使 GPU 花费尽可能多的计算时间,这取决于使用较小矩阵大小的试验。但是似乎没有运行内核代码(包括 for 循环之外的部分)(输出矩阵自初始化以来没有任何元素发生变化)。如果我将矩阵大小增加到 500 左右,如果我将 for 循环中的限制器设置为某个低值(例如 3),我有时可以让内核运行。
我是否在这里遇到了一些硬件限制,或者有什么技巧可以让这些 for 循环适用于大型矩阵?
这是一个完整的代码示例,您可以将其复制到 .cu 文件中。内核尝试将矩阵 A (W*H) 的内容复制到矩阵 B (W*H)。输出显示了两个矩阵的第一个元素,对于 W*H
#include <cuda.h>
#include <cuda_runtime.h>
#include <cuda_runtime_api.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <iostream>
#include <time.h>
#define gpuErrchk(ans) { gpuAssert((ans), __FILE__, __LINE__); }
inline void gpuAssert(cudaError_t code, char *file, int line, bool abort=true)
{
if (code != cudaSuccess)
{
fprintf(stderr,"GPUassert: %s %s %d\n", cudaGetErrorString(code), file, line);
if (abort) exit(code);
}
}
__global__ void MatrixCopy(float *A, float *B, int W)
{
int i = blockIdx.x*blockDim.x + threadIdx.x;
int j = blockIdx.y*blockDim.y + threadIdx.y;
B[j*W + i]=A[j*W + i];
}
int main(void)
{
clock_t start1=clock();
int W=1000;
int H=1000;
float *A, *B;
float *devA, *devB;
A=(float*)malloc(W*H*sizeof(float));
B=(float*)malloc(W*H*sizeof(float));
for(int i=0; i<=W*H; i++)
{
A[i]=rand() % 3;
A[i]=A[i]+1;
B[i]=0;
}
gpuErrchk( cudaMalloc( (void**)&devA, W*H*sizeof(float) ) );
gpuErrchk( cudaMalloc( (void**)&devB, W*H*sizeof(float) ) );
gpuErrchk( cudaMemcpy( devA, A, W*H*sizeof(float), cudaMemcpyHostToDevice ) );
gpuErrchk( cudaMemcpy( devB, B, W*H*sizeof(float), cudaMemcpyHostToDevice ) );
dim3 threads(32,32);
int bloW=(int)ceil((double)W/32);
int bloH=(int)ceil((double)H/32);
dim3 blocks(bloW, bloH);
clock_t finish1=clock();
clock_t start2=clock();
MatrixCopy<<<blocks,threads>>>(devA, devB, W);
gpuErrchk( cudaPeekAtLastError() );
gpuErrchk( cudaMemcpy( B, devB, W*H*sizeof(float), cudaMemcpyDeviceToHost ) );
clock_t finish2=clock();
printf("\nGPU calculation time (ms): %d\nInitialization time (ms): %d\n\n", (int)ceil(double(((finish2-start2)*1000/(CLOCKS_PER_SEC)))), (int)ceil(double(((finish1-start1)*1000/(CLOCKS_PER_SEC)))));
printf("\n%f\n", A[0]);
printf("\n%f\n\n", B[0]);
gpuErrchk( cudaFree(devA) );
gpuErrchk( cudaFree(devB) );
free(A);
free(B);
#ifdef _WIN32
system ("PAUSE");
#endif
return 0;
}
【问题讨论】:
-
您需要提供有关您的问题的更详细信息以及源代码。以上信息不足。
-
你的意思是你在递归内核?
-
不,没有递归。
-
也许你也有类似here的问题。您的内核只需要很长时间来计算并被系统终止。
-
最好的办法是提供一个最小大小的代码,用完整的CUDA error checking 以及您正在使用的硬件(您担心硬件限制)和编译字符串来重现您的问题。