CUDA中的位阵列

CUDA中的位阵列,c,cuda,C,Cuda,我在CUDA中实现了埃拉托斯烯筛,我有一个非常奇怪的输出。我使用unsigned char*作为数据结构,并使用以下宏操作位 #define ISBITSET(x,i) ((x[i>>3] & (1<<(i&7)))!=0) #define SETBIT(x,i) x[i>>3]|=(1<<(i&7)); #define CLEARBIT(x,i) x[i>>3]&=(1<<(i&7)

我在CUDA中实现了埃拉托斯烯筛,我有一个非常奇怪的输出。我使用unsigned char*作为数据结构,并使用以下宏操作位

#define ISBITSET(x,i) ((x[i>>3] & (1<<(i&7)))!=0)
#define SETBIT(x,i) x[i>>3]|=(1<<(i&7));
#define CLEARBIT(x,i) x[i>>3]&=(1<<(i&7))^0xFF;

#定义ISBITSET(x,i)((x[i>>3]&(13]|=(13)]&=(1我建议将宏替换为要开始使用的方法。您可以使用前面有
\uuuuu host\uuuuu
\uuu device\uuuuuu
的方法在必要时生成特定于cpp和cu的版本。这将消除预处理器执行意外操作的可能性


现在只需调试导致错误输出的特定代码分支,依次检查每个阶段是否正确,您就会发现问题。

多个线程同时访问全局内存中的同一个字(char),因此写入的结果会损坏


您可以使用原子操作来防止这种情况,但更好的解决方案是改变您的算法:与其让每个线程筛选出2、3、4、5的倍数,不如让每个线程检查一个类似[0..7]、[8..15]的范围,…因此,每个范围的长度都是8位的倍数,不会发生冲突。

我会检查这一点,但经过一些思考后,我认为问题是由于试图更改同一字符的值的线程之间的竞争条件造成的,我会返回我的发现。谢谢,我会使用更大的字,如short或int来存储位数组,因为“(若半包装中线程的读写可以合并为32、64或128字节,则对全局内存的内存访问最快)”。
size_t p=3;
size_t primeTill = 30;

while(p*p<=primeTill)
{
    if(ISBITSET(h_a, p) == 1){
        int dimA = 30;
        int numBlocks = 1;
        int numThreadsPerBlock = dimA;
        dim3 dimGrid(numBlocks);
        dim3 dimBlock(numThreadsPerBlock);
        cudaMemcpy( d_a, h_a, memSize, cudaMemcpyHostToDevice );        
        cudaThreadSynchronize();    
        reverseArrayBlock<<< dimGrid, dimBlock >>>( d_a, primeTill, p );
        cudaThreadSynchronize();    
        cudaMemcpy( h_a, d_a, memSize, cudaMemcpyDeviceToHost );
        cudaThreadSynchronize();    
        printf("This is after removing multiples of %d\n", p);
        //Loop
        for(size_t i = 0; i < primeTill +1; i++)
        {
            printf("Bit %d is %d\n", i, ISBITSET(h_a, i));
        }
    }           
    p++;
}
__global__ void reverseArrayBlock(unsigned char *d_out, int size, size_t p)
{
int id = blockIdx.x*blockDim.x + threadIdx.x;
int r = id*p;
if(id >= p && r <= size )
{
    while(ISBITSET(d_out, r ) == 1 ){
        CLEARBIT(d_out, r);
    }

    // if(r == 9)
    // {
    //  /* code */
    //  CLEARBIT(d_out, 9);
    // }

}