是否可以在 GPU 上生成 uint64_t 随机数?

Dim*_*off 0 random cuda gpgpu uint64 curand

我正在尝试将有限域 CPU 代码移植到 GPU 上,在此过程中,我想生成随机向量来测试函数的速度。

我需要两个随机向量uint64_t(以及相应的两个 double 向量,具有有限域元素的浮点表示),每个向量的大小为 N。 据我所知,uint64_t 类型在 GPU 上不受本机支持,并且使用两个 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;
}
Run Code Online (Sandbox Code Playgroud)

Nvcc 返回au调用中具有不兼容类型的信息curandGenerateLongLong。根据 Curand API,我只能使用 SOBOL64 拟随机生成器。为什么会这样呢?是否有一些伪随机生成器uint64_t或适合我的情况的准随机生成器?

如果我想避免准随机生成,我必须在 CPU 上随机生成并将随机向量复制到 GPU。我可以将设备 curand 库 (curand_kernel.h) 用于我的用例吗?

Rob*_*lla 5

uint64_t在 CUDA 支持的 Linux 64 位上(至少),和的表示和语义之间没有数值差异unsigned long long。我承认类型不同,但这里的差异对于您在此处显示的用例没有意义。

您将代码修改如下应该没问题:

curandGenerateLongLong(gen_type, (unsigned long long *)au, p);
Run Code Online (Sandbox Code Playgroud)

你会得到一个uint64_t生成的数组。

(在64 位 Windows上,我怀疑您甚至不会收到您报告的错误,但我还没有测试过。)

  • 作为附录,回答标题问题:任何 64 位 PRNG 都可以部署在设备代码中。“cuRand”只是一个方便的库,可以为程序员处理潜在棘手的并行化和初始化问题。没有什么可以阻止 CUDA 程序员在设备代码中部署他们最喜欢的 64 位 PRNG(例如,我偏爱 Marsaglia 的 KISS64),并且对于各种用例,甚至可能没有必要确保每个线程消耗的随机数是保证完全独立。 (4认同)