1. 介绍
mcRAND 库提供的功能侧重于简单高效地生成高质量的伪随机数和准随机数。
伪随机数序列满足大部分真随机序列的统计特性,但是它是由确定性算法生成的。
n 维点的准随机数序列是由一种确定性算法生成的,该算法旨在均匀地填充一个 n 维空间。
1.1. 安装
安装 MXMACA® 工具包将会把RAND头文件(mcrand.h 和 mcrand_kernel.h)以及库文件(libmcrand.so 和 libmcrand_static.a)复制到您系统的标准MXMACA包含目录中。 MXMACA工具包的安装,参见《曦云系列通用计算GPU 快速上手指南》。安装后,确保设置了环境变量MACA_PATH。
export MACA_PATH=/opt/maca
这里的 /opt/maca 路径为MXMACA工具包的默认安装路径。如果安装时选择了其它路径,则将MACA_PATH设置为该路径。 以下是与RAND API相关的文件列表。
#header
${MACA_PATH}/include/mcrand/mcrand.h
${MACA_PATH}/include/mcrand/mcrand_kernel.h
#libraries
${MACA_PATH}/lib/libmcrand.so
${MACA_PATH}/lib/libmcrand_static.a
mcRAND由两部分组成:主机(CPU)端的库和设备(GPU)端的头文件。
主机端的库类似于其他CPU库:用户需要包含头文件 ${MACA_PATH}/include/mcrand/mcrand.h 以获取函数声明,并链接到库文件。随机数可以在设备端或主机CPU上生成。
对于 device generation ,库的调用发生在主机上,但随机数生成的实际工作发生在设备上。生成的随机数存储在设备的全局内存中。用户可以调用自己的内核来使用这些随机数,或者将随机数复制回主机进行进一步处理。
对于 host CPU generation ,所有的工作都在主机上完成,随机数存储在主机内存中。
mcRAND的第二部分是设备端的头文件 ${MACA_PATH}/include/mcrand/mcrand_kernel.h 。
该文件定义了用于设置随机数生成器状态和生成随机数序列的设备函数。用户代码可以包含这个头文件,并且用户编写的内核可以调用头文件中定义的设备函数。这使得随机数可以被生成并立即被用户内核使用,而不需要将随机数写入全局内存然后再读取。
1.2. Hello mcRAND
以下是一个使用mcRAND API的简单示例:
/*
* 这个程序使用主机MCRAND API生成100个随机数。
* 伪随机浮点数。
*/
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <stdexcept>
#include <vector>
#include <mc_runtime.h>
#include <mcrand.h>
int main(int argc, char *argv[]) {
mcStream_t stream = NULL;
mcrandGenerator_t gen = NULL;
mcrandOrdering_t order = MCRAND_ORDERING_PSEUDO_BEST;
const int n = 10;
const unsigned long long offset = 0ULL;
const unsigned long long seed = 1234ULL;
const float mean = 1.0f;
const float stddev = 2.0f;
mcStreamCreateWithFlags(&stream, mcStreamNonBlocking);
std::vector<float> h_data(n, 0);
float *d_data = nullptr;
mcMalloc(reinterpret_cast<void **>(&d_data),
sizeof(float) * h_data.size());
mcrandCreateGenerator(&gen, MCRAND_RNG_PSEUDO_XORWOW);
mcrandSetStream(gen, stream);
mcrandSetGeneratorOffset(gen, offset);
mcrandSetGeneratorOrdering(gen, order);
mcrandSetPseudoRandomGeneratorSeed(gen, seed);
mcrandGenerateLogNormal(gen, d_data, h_data.size(), mean, stddev);
mcMemcpyAsync(h_data.data(), d_data,
sizeof(float) * h_data.size(),
mcMemcpyDeviceToHost, stream);
mcStreamSynchronize(stream);
mcFree(d_data);
mcrandDestroyGenerator(gen);
mcStreamDestroy(stream);
mcDeviceReset();
return EXIT_SUCCESS;
}
假设上面的示例包含在名为myMcrandApp.cpp的文件中,在Linux上使用mxcc编译器对其进行编译,并链接到动态库,可以使用以下命令:
export MACA_PATH=/opt/maca
export MACA_CLANG_PATH=${MACA_PATH}/mxgpu_llvm/bin
export LD_LIBRARY_PATH=${MACA_PATH}/lib:${LD_LIBRARY_PATH}
${MACA_CLANG_PATH}/mxcc myMcrandApp.cpp \
-I${MACA_PATH}/include/mcrand \
-lmcrand -o myMcrandApp
这里的 /opt/maca 路径为MXMACA工具包的默认安装路径。如果安装时选择了其它路径,则将MACA_PATH设置为该路径。
而要编译针对静态mcRAND库的应用程序,则需要使用以下命令:
export MACA_PATH=/opt/maca
export MACA_CLANG_PATH=${MACA_PATH}/mxgpu_llvm/bin
export LD_LIBRARY_PATH=${MACA_PATH}/lib:${LD_LIBRARY_PATH}
${MACA_CLANG_PATH}/mxcc myMcrandApp.cpp \
-I${MACA_PATH}/include/mcrand \
-lmcrand_static -o myMcrandApp
这里的 /opt/maca 路径为MXMACA工具包的默认安装路径。如果安装时选择了其它路径,则将MACA_PATH设置为该路径。