C++ CUDA内核中的While循环失败
我用GPU做一些文字处理的计算。 最初,我使用一个块(500个线程)来处理一个字。 要处理100个字,我必须在主函数中循环内核函数100次C++ CUDA内核中的While循环失败,c++,cuda,C++,Cuda,我用GPU做一些文字处理的计算。 最初,我使用一个块(500个线程)来处理一个字。 要处理100个字,我必须在主函数中循环内核函数100次 for (int i=0; i<100; i++) kernel <<< 1, 500 >>> (length_of_word); 现在我想同时处理所有100个单词 每个块仍将有500个线程,并处理一个字(每个块) dev_totalwordarray:存储单词的所有字符(一个接一个) dev_lengt
for (int i=0; i<100; i++)
kernel <<< 1, 500 >>> (length_of_word);
现在我想同时处理所有100个单词
每个块仍将有500个线程,并处理一个字(每个块)
dev_totalwordarray:存储单词的所有字符(一个接一个)
dev_length_数组:存储每个单词的长度
dev_accu_length:存储单词的累计长度(之前所有单词的总字符数)
dev_salt_是一个大小为500的数组,存储无符号整数
因此,在我的主要职能中
kernel2 <<< 100, 500 >>> (dev_totalwordarray, dev_length_array, dev_accu_length, dev_salt_);
我的函数内核现在如下所示:
__global__ void kernel (int *dev_length)
{
int length = *dev_length;
while (length > 4)
{ //do something;
length -=4;
}
}
__global__ void kernel2 (char* dev_totalwordarray, int *dev_length_array, int* dev_accu_length, unsigned int* dev_salt_)
{
tid = threadIdx.x + blockIdx.x * blockDim.x;
unsigned int hash[N];
int length = dev_length_array[blockIdx.x];
while (tid < 50000)
{
const char* itr = &(dev_totalwordarray[dev_accu_length[blockIdx.x]]);
hash[tid] = dev_salt_[threadIdx.x];
unsigned int loop = 0;
while (length > 4)
{ const unsigned int& i1 = *(reinterpret_cast<const unsigned int*>(itr)); itr += sizeof(unsigned int);
const unsigned int& i2 = *(reinterpret_cast<const unsigned int*>(itr)); itr += sizeof(unsigned int);
hash[tid] ^= (hash[tid] << 7) ^ i1 * (hash[tid] >> 3) ^ (~((hash[tid] << 11) + (i2 ^ (hash[tid] >> 5))));
length -=4;
}
tid += blockDim.x * gridDim.x;
}
}
\uuuuu全局\uuuuuu无效内核2(char*dev\u totalwordarray,int*dev\u length\u array,int*dev\u累计长度,无符号int*dev\u salt\u2)
{
tid=线程IDX.x+块IDX.x*块DIM.x;
无符号整数散列[N];
int length=dev_length_数组[blockIdx.x];
而(tid<50000)
{
const char*itr=&(dev_totalwordarray[dev_accu_length[blockIdx.x]];
hash[tid]=dev_salt[threadIdx.x];
无符号整数循环=0;
而(长度>4)
{const unsigned int&i1=*(reinterpret_cast(itr));itr+=sizeof(unsigned int);
常量unsigned int&i2=*(重新解释强制转换(itr));itr+=sizeof(unsigned int);
hash[tid]^=(hash[tid]>3)^(~(hash[tid]>5));
长度-=4;
}
tid+=blockDim.x*gridDim.x;
}
}
然而,内核2似乎根本不起作用
似乎是而(长度>4)
导致了这种情况
有人知道为什么吗?谢谢。我不确定while是否是罪魁祸首,但我发现您的代码中没有什么让我担心的东西:
- 您的内核不产生任何输出。优化器很可能会检测到这一点,并将其转换为空内核
- 在几乎任何情况下,您都不希望为每个线程分配数组。这将消耗大量内存。您的
表将按线程分配,并在内核末尾丢弃。如果hash[N]
很大(然后乘以线程总数),您可能会耗尽GPU内存。更不用说,访问N
几乎和访问全局内存一样慢散列
- 块中的所有线程将具有相同的
值。这是有意的吗itr
- 每个线程只初始化自己的
哈希表副本中的一个字段
- 我看到
其中hash[tid]
是一个全局索引。请注意,即使将tid
哈希设置为全局,也可能会遇到并发问题。并非网格中的所有块都将同时运行。虽然一个块将初始化
散列的一部分,但另一个块甚至可能不会启动李>
hash[tid]
-这是预期的行为吗?另外-来自同一块的所有线程将从dev\u totalwordarray
读取完全相同的内容。因此,hash[tid]
中的输出将只因dev_salt
的内容不同而不同;每个线程将处理整个单词。是的,你是对的。每个线程将处理整个单词,来自同一块的线程将处理同一个单词。如果这是您想要的,那么它应该可以工作。“根本不起作用”背后隐藏着什么?发射失败?输出错误。。。。编译时没有错误,但内核似乎没有被处理。我试着在while(tid<50000)中放入printf行,但没有打印任何内容(除非while(长度>4)被注释掉)。这就是为什么我认为(长度>4)是问题的主要原因。
int* dev_array_of_word_length;
HANDLE_ERROR( cudaMalloc( (void**)&dev_array_of_word_length, 100 * sizeof(int) ) );
HANDLE_ERROR( cudaMemcpy( dev_array_of_word_length, actualwordlength2, 100 * sizeof(int),
__global__ void kernel2 (char* dev_totalwordarray, int *dev_length_array, int* dev_accu_length, unsigned int* dev_salt_)
{
tid = threadIdx.x + blockIdx.x * blockDim.x;
unsigned int hash[N];
int length = dev_length_array[blockIdx.x];
while (tid < 50000)
{
const char* itr = &(dev_totalwordarray[dev_accu_length[blockIdx.x]]);
hash[tid] = dev_salt_[threadIdx.x];
unsigned int loop = 0;
while (length > 4)
{ const unsigned int& i1 = *(reinterpret_cast<const unsigned int*>(itr)); itr += sizeof(unsigned int);
const unsigned int& i2 = *(reinterpret_cast<const unsigned int*>(itr)); itr += sizeof(unsigned int);
hash[tid] ^= (hash[tid] << 7) ^ i1 * (hash[tid] >> 3) ^ (~((hash[tid] << 11) + (i2 ^ (hash[tid] >> 5))));
length -=4;
}
tid += blockDim.x * gridDim.x;
}
}