我正在开发一个CUDA光线平面交叉核。
我们假设,我的平面(面)结构是:
typedef struct _Face {
int ID;
int matID;
int V1ID;
int V2ID;
int V3ID;
float V1[3];
float V2[3];
float V3[3];
float reflect[3];
float emmision[3];
float in[3];
float out[3];
int intersects[RAYS];
} Face;
我粘贴了整个结构,以便您可以了解它的大小。当前配置中 RAYS 等于 625 。在下面的代码中假设faces数组的大小是1270(通常是 - 数千)。
直到今天,我已经以一种非常天真的方式启动了我的内核:
const int tpb = 64; //threads per block
dim3 grid = (n +tpb-1)/tpb; // n - face count in array
dim3 block = tpb;
//.. some memory allocation etc.
theKernel<<<grid,block>>>(dev_ptr, n);
在内核中我有一个循环:
__global__ void theKernel(Face* faces, int faceCount) {
int offset = threadIdx.x + blockIdx.x*blockDim.x;
if(offset >= faceCount)
return;
Face f = faces[offset];
//..some initialization
int RAY = -1;
for(float alpha=0.0f; alpha<=PI; alpha+= alpha_step ){
for(float beta=0.0f; beta<=PI; beta+= beta_step ){
RAY++;
//..calculation per ray in (alpha,beta) direction ...
faces[offset].intersects[RAY] = ...; //some assignment
这是关于它的。我循环了所有方向并更新了 faces 数组。我工作正常,但几乎没有CPU代码快。
所以今天我尝试优化代码,并使用更多线程启动内核。我不希望每个面具有 1个线程,而是希望每个面部的光线 1个线程(意味着625个线程适用于1个面)。修改很简单:
dim3 grid = (n*RAYS +tpb-1)/tpb; //before launching . RAYS = 625, n = face count
和内核本身:
__global__ void theKernel(Face *faces, int faceCount){
int threadNum = threadIdx.x + blockIdx.x*blockDim.x;
int offset = threadNum/RAYS; //RAYS is a global #define
int rayNum = threadNum - offset*RAYS;
if(offset >= faceCount || rayNum != 0)
return;
Face f = faces[offset];
//initialization and the rest.. again ..
此代码不根本不起作用。为什么?从理论上讲,只有第一个线程(每个面部625个)应该可以工作,那么为什么会导致计算不良(几乎没有)?
亲切的问候, 即
答案 0 :(得分:0)
任何维度中网格的最大大小为65535(CUDA programming guide,附录F)。如果在更改之前网格大小为1000,则将其增加到625000.这大于限制,因此内核将无法正常运行。
如果将网格大小定义为
dim3 grid((n + tpb - 1) / tpb, RAYS);
然后所有网格尺寸都小于限制。您还必须更改内核中blockIdx
的使用方式。
答案 1 :(得分:0)
正如Heatsink所指出,你可能已经超出了可用资源。好主意是在内核执行后检查是否没有错误。
这是我使用的C ++代码:
#include <cutil_inline.h>
void
check_error(const char* str, cudaError_t err_code) {
if (err_code != ::cudaSuccess)
std::cerr << str << " -- " << cudaGetErrorString(err_code) << "\n";
}
然后当我侵犯内核时:
my_kernel <<<block_grid, thread_grid >>>(args);
check_error("my_kernel", cudaGetLastError());