我需要启动N个线程(在一个块中)
这是代码,'e'是1024b的bignumber。我需要在gpu上复制它并一点一点地读取它。
主机代码:
unsigned char *__e;
BIGNUM *e = BN_new();
unsigned char exp[128];
// e
i = cudaMalloc( (void**)&__e, 128* sizeof(unsigned char) );
if(i != cudaSuccess)
printf("cudaMalloc __e FAIL! Code: %d\n", i);
BN_bn2bin128B(e, exp); // copy data in exp
for(i=0; i<128; i++)
exp[i] = reverse(exp[i]);
i = cudaMemcpy( __e, exp, 128* sizeof(unsigned char), cudaMemcpyHostToDevice);
if(i != cudaSuccess)
printf("cudaMemcpy __e FAIL! Code: %d\n", i);
unsigned char reverse(unsigned char b) {
b = (b & 0xF0) >> 4 | (b & 0x0F) << 4;
b = (b & 0xCC) >> 2 | (b & 0x33) << 2;
b = (b & 0xAA) >> 1 | (b & 0x55) << 1;
return b;
}
设备代码:
for(int i=0; i<1024; i++)
if(ISBITSET(__e, i) == 1)
//do something
部首:
#define ISBITSET(x,i) ((x[i>>3] & (1<<(i&7)))!=0)
不幸的是,ISBITSET不接受与__e不同的任何内容,所以我无法检查__e本身的其他值
我该如何解决?或者有更好的方法吗?
答案 0 :(得分:2)
GPU是32位机器,因此您需要一次处理1024位32位,而不是8位。因此,您应该将所有unsigned char
替换为unsigned int
并调整相应的价值观。
GPU具有快速PTX指令,可以一次反转32位,因此您可能希望在GPU上实现该指令。该指令称为brev
。要使用它,您可以添加内联PTX,类似这样(未经测试):
asm("brev.b32 %0, %1;" : "=r"(dst_var) : "r"(src_var));
有关详细信息,请参阅NVIDIA的文档“在CUDA中使用Inline PTX程序集”。
for(int i=0; i<1024; i++)
if(ISBITSET(__e, i) == 1)
//do something
此代码可能存在性能问题。假设有一个50%的可能性,你只能得到50%的可能性能,因为你的一半线程必须等待而另一半执行//do something
。我想不出一个解决方法。您可能还想启动线程而不是循环。
不幸的是,ISBITSET不接受与__e不同的任何内容,所以我无法检查__e本身的其他值
你能详细说明吗? ISBITSET
宏看起来不错,看起来它可以处理任何无符号字符数组,这就是__e
。