我想编写一个CUDA程序,它返回一个包含特定条件的更大数组的位置。
执行此操作的简单方法是编写一个内核,如果保留条件,则返回一个整数数组,如果不符合,则返回0。
另一种方法可能只返回找到的索引 - 但根据我对GPU同步的了解(这相当于在GPU上实现队列/链接列表)会产生问题。
提出的第一个想法的问题是数组将处于输入大小。
我想到的另一种方法是创建一个大小为log(n)/ 8 + 1的数组(n =我检查的项目数),并为每个数组位置使用1位(保持一种压缩表示形式)输出)。
我唯一找不到的是CUDA是否支持并行位寻址..
我现在如何做的一个例子:
__global__ void test_kernel(char *gpu, char *gpuFind, int *gputSize, int *gputSearchSize, int *resultsGPU)
{
int start_idx = threadIdx.x + (blockIdx.x * blockDim.x);
if (start_idx > *gputTextSize - *gputSearchSize){return;}
unsigned int wrong=0;
for(int i=0; i<*gputSearchSize;i++){
wrong = calculationOnGpu(gpuText, gpuFind, start_idx,i, gputSearchSize);
}
resultsGPU[start_idx] = !wrong;
}
我想要做的不是使用int或char作为“resultsGpu”变量,而是使用别的东西。
由于
答案 0 :(得分:4)
在1,2,4,8或16 字节的边界上的CUDA GPU can access items。它无法独立访问字节中的位。
通过读取更大的项目(例如char
或int
),修改寄存器中的位,然后将该项目写回存储器,可以修改字节中的位。因此,它将是一个读 - 修改 - 写操作。
为了在具有多个线程的场景中保留相邻位,有必要以原子方式更新项(char
,int
等等。)没有原子操作{ {1}}数量,因此需要将这些位分组为32的数量,并写入例如为char
。遵循这个习惯用法,每个线程都会进行原子操作。
32当前也恰好是扭曲尺寸,因此基于扭曲的内在可能是更有效的方式,特别是warp vote int
函数。像这样:
__ballot()
您还没有提供完整的代码,因此上面只是一个如何完成的草图。我不确定原始内核中的循环无论如何都是一种有效的方法,并且上面假设每个数据项要搜索1个线程。即使在搜索到的数组的一端或另一端存在非活动线程时,__global__ void test_kernel(char *gpu, char *gpuFind, int *gputSize, int *gputSearchSize, int *resultsGPU)
{
int start_idx = threadIdx.x + (blockIdx.x * blockDim.x);
if (start_idx > *gputTextSize - *gputSearchSize){return;}
unsigned int wrong=0;
wrong = calculationOnGpu(gpuText, gpuFind, start_idx,0, gputSearchSize);
wrong = __ballot(wrong);
if ((threadIdx.x & 31) == 0)
resultsGPU[start_idx/32] = wrong;
}
也应该是安全的。