我正在使用GPU进行一些处理单词的计算。 最初,我使用一个块(有500个线程)来处理一个单词。 要处理100个单词,我必须在我的main函数中循环内核函数100次。
for (int i=0; i<100; i++)
kernel <<< 1, 500 >>> (length_of_word);
我的内核函数如下所示:
__global__ void kernel (int *dev_length)
{
int length = *dev_length;
while (length > 4)
{ //do something;
length -=4;
}
}
现在我想同时处理所有100个单词。
每个块仍然有500个线程,并处理一个字(每个块)。
dev_totalwordarray:存储单词的所有字符(一个接一个)
dev_length_array:存储每个单词的长度。
dev_accu_length:存储单词的累计长度(所有前一个单词的总字符数)
dev_salt_是一个大小为500的数组,存储无符号整数。
因此,在我的主要功能中我有
kernel2 <<< 100, 500 >>> (dev_totalwordarray, dev_length_array, dev_accu_length, dev_salt_);
填充cpu数组:
for (int i=0; i<wordnumber; i++)
{
int length=0;
while (word_list_ptr_array[i][length]!=0)
{
length++;
}
actualwordlength2[i] = length;
}
从cpu复制 - &gt; GPU:
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;
}
}
但是,kernel2似乎根本不起作用。
似乎while (length > 4)
导致了这一点。
有谁知道为什么?感谢。
答案 0 :(得分:1)
我不确定while
是否是罪魁祸首,但我发现代码中的一些事情让我担心:
hash[N]
表将按线程分配,并在内核结束时丢弃。如果N
很大(然后再乘以线程总数),则可能会耗尽GPU内存。更不用说,访问hash
几乎与访问全局内存一样慢。itr
值。这是打算吗?hash
表副本中初始化一个字段。hash[tid]
其中tid
是全局索引。请注意,即使hash
是全局的,您也可能遇到并发问题。并非网格中的所有块都将同时运行。虽然一个块将初始化hash
的一部分,但另一个块甚至可能无法启动!