我正试图将有限域CPU代码移植到GPU上,在此过程中,我想生成随机向量来测试我的函数的速度。
我需要uint64_t
的两个随机向量(以及对应的两个double向量,用有限域元素的浮点表示),每个向量的大小为N。据我所知,GPU不支持uint64_t类型,使用两个32位寄存器进行模拟。
这些向量将包含范围为(0,p-1)的整数,其中p是素数,例如(1<<25) - 39。(这个素数使用25位,但我仍然需要64位,在剩余之前存储中间结果)。
我试图理解Curand API并使用它生成随机向量。
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <cuda.h>
#include <time.h>
#include <curand.h>
int main() {
uint64_t p = (1 << 25) - 39;
const uint32_t N = (1 << 27);
uint64_t *au;
double *ad;
cudaError_t handle;
handle = cudaMallocManaged(&au, N*sizeof(uint64_t));
handle = cudaMallocManaged(&ad, N*sizeof(double));
curandGenerator_t gen_type;
curandCreateGenerator(&gen_type, CURAND_RNG_PSEUDO_MRG32K3A);
curandSetPseudoRandomGeneratorSeed(gen_type, (uint64_t)time(NULL));
curandGenerateLongLong(gen_type, au, p);
cudaFree(au);
cudaFree(ad);
return 0;
}
Nvcc返回au
在curandGenerateLongLong
调用中具有不兼容的类型。根据Curand API,我被限制使用SOBOL64准随机生成器。为什么会这样呢?是否有一些伪随机生成器uint64_t
或准随机生成器适应我的情况?
如果我想避免准随机生成,我被迫在CPU上随机生成并将我的随机向量复制到GPU。我可以为我的用例使用设备curand库(curand_kernel.h)吗?
在CUDA支持的64位linux上(至少),uint64_t
和unsigned long long
的表示和语义之间没有数值差异。我承认类型是不同的,但是这里的区别对于您在这里展示的用例来说没有意义。
你可以这样修改你的代码:
curandGenerateLongLong(gen_type, (unsigned long long *)au, p);
,您将得到生成的uint64_t
数组。
(在64位windows上,我怀疑你甚至不会得到你报告的错误,但我还没有测试过。)