- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
上下文:我目前正在学习如何正确使用 CUDA,特别是如何使用 CURAND 生成随机数。我学会了here当我需要随机数时,在我的代码中执行核心计算的内核中直接生成随机数可能是明智的。
在 documentation 之后,我决定尝试一下,尝试编写一段简单的运行代码,稍后我可以根据自己的需要进行调整。
我排除了 MTGP32,因为一个 block 中有 256 个并发线程的限制(并且只有 200 个预生成的参数集)。此外,我不想使用 double ,所以我决定坚持使用默认生成器 (XORWOW)。
问题:我很难理解为什么我的代码中的相同种子值会为大于 128 的每个 block 的多个线程生成不同的数字序列(当 blockSize<129 时,所有内容按我的预期运行)。做适当的事后 CUDA error checking ,正如罗伯特在他的评论中所建议的那样,很明显硬件限制起了作用。此外,在编译时不使用“-G -g”标志会将“阈值问题”从 128 提高到 384。
问题:到底是什么原因造成的?罗伯特在他的评论中写到“这可能是每个线程的寄存器问题”。这是什么意思?有没有一种简单的方法可以查看硬件规范并说明此限制在哪里?我可以在不必为每个线程生成更多随机数的情况下解决这个问题吗?
似乎已经讨论了一个相关问题here但我认为它不适用于我的情况。
我的代码(见下文)主要受 these examples 启发.
代码:
#include <stdio.h>
#include <stdlib.h>
#include <cuda.h>
#include <curand_kernel.h>
#define gpuErrchk(ans) { gpuAssert((ans), __FILE__, __LINE__); }
inline void gpuAssert(cudaError_t code, char *file, int line, bool abort=true){
if (code != cudaSuccess){
fprintf(stderr,"GPUassert: %s %s %d\n", cudaGetErrorString(code), file, line);
if (abort) exit(code);
}
}
__global__ void setup_kernel(curandState *state, int seed, int n){
int id = threadIdx.x + blockIdx.x*blockDim.x;
if(id<n){
curand_init(seed, id, 0, &state[id]);
}
}
__global__ void generate_uniform_kernel(curandState *state, float *result, int n){
int id = threadIdx.x + blockIdx.x*blockDim.x;
float x;
if(id<n){
curandState localState = state[id];
x = curand_uniform(&localState);
state[id] = localState;
result[id] = x;
}
}
int main(int argc, char *argv[]){
curandState *devStates;
float *devResults, *hostResults;
int n = atoi(argv[1]);
int s = atoi(argv[2]);
int blockSize = atoi(argv[3]);
int nBlocks = n/blockSize + (n%blockSize == 0?0:1);
printf("\nn: %d, blockSize: %d, nBlocks: %d, seed: %d\n", n, blockSize, nBlocks, s);
hostResults = (float *)calloc(n, sizeof(float));
cudaMalloc((void **)&devResults, n*sizeof(float));
cudaMalloc((void **)&devStates, n*sizeof(curandState));
setup_kernel<<<nBlocks, blockSize>>>(devStates, s, n);
gpuErrchk( cudaPeekAtLastError() );
gpuErrchk( cudaDeviceSynchronize() );
generate_uniform_kernel<<<nBlocks, blockSize>>>(devStates, devResults, n);
gpuErrchk( cudaPeekAtLastError() );
gpuErrchk( cudaDeviceSynchronize() );
cudaMemcpy(hostResults, devResults, n*sizeof(float), cudaMemcpyDeviceToHost);
for(int i=0; i<n; i++) {
printf("\n%10.13f", hostResults[i]);
}
cudaFree(devStates);
cudaFree(devResults);
free(hostResults);
return 0;
}
我编译了两个二进制文件,一个使用“-G -g”调试标志,另一个没有。我分别将它们命名为 rng_gen_d 和 rng_gen:
$ nvcc -lcuda -lcurand -O3 -G -g --ptxas-options=-v rng_gen.cu -o rng_gen_d
ptxas /tmp/tmpxft_00002257_00000000-5_rng_gen.ptx, line 2143; warning : Double is not supported. Demoting to float
ptxas info : 77696 bytes gmem, 72 bytes cmem[0], 32 bytes cmem[14]
ptxas info : Compiling entry function '_Z12setup_kernelP17curandStateXORWOWii' for 'sm_10'
ptxas info : Used 43 registers, 32 bytes smem, 72 bytes cmem[1], 6480 bytes lmem
ptxas info : Compiling entry function '_Z23generate_uniform_kernelP17curandStateXORWOWPfi' for 'sm_10'
ptxas info : Used 10 registers, 36 bytes smem, 40 bytes cmem[1], 48 bytes lmem
$ nvcc -lcuda -lcurand -O3 --ptxas-options=-v rng_gen.cu -o rng_gen
ptxas /tmp/tmpxft_00002b73_00000000-5_rng_gen.ptx, line 533; warning : Double is not supported. Demoting to float
ptxas info : 77696 bytes gmem, 72 bytes cmem[0], 32 bytes cmem[14]
ptxas info : Compiling entry function '_Z12setup_kernelP17curandStateXORWOWii' for 'sm_10'
ptxas info : Used 20 registers, 32 bytes smem, 48 bytes cmem[1], 6440 bytes lmem
ptxas info : Compiling entry function '_Z23generate_uniform_kernelP17curandStateXORWOWPfi' for 'sm_10'
ptxas info : Used 19 registers, 36 bytes smem, 4 bytes cmem[1]
首先,在编译时有一条奇怪的警告消息(见上文):
ptxas /tmp/tmpxft_00002b31_00000000-5_rng_gen.ptx, line 2143; warning : Double is not supported. Demoting to float
一些调试显示导致此警告的行是:
curandState localState = state[id];
没有声明 double ,所以我不知道如何解决这个问题(或者即使这需要解决)。
现在,我面临的(实际)问题的一个例子:
$ ./rng_gen_d 5 314 127
n: 5, blockSize: 127, nBlocks: 1, seed: 314
0.9151657223701
0.3925153017044
0.7007563710213
0.8806988000870
0.5301177501678
$ ./rng_gen_d 5 314 128
n: 5, blockSize: 128, nBlocks: 1, seed: 314
0.9151657223701
0.3925153017044
0.7007563710213
0.8806988000870
0.5301177501678
$ ./rng_gen_d 5 314 129
n: 5, blockSize: 129, nBlocks: 1, seed: 314
GPUassert: too many resources requested for launch rng_gen.cu 54
第 54 行是在 setup_kernel() 之后的 gpuErrchk()。
对于其他二进制文件(编译时没有“-G -g”标志),“故障阈值”提高到 384:
$ ./rng_gen 5 314 129
n: 5, blockSize: 129, nBlocks: 1, seed: 314
0.9151657223701
0.3925153017044
0.7007563710213
0.8806988000870
0.5301177501678
$ ./rng_gen 5 314 384
n: 5, blockSize: 384, nBlocks: 1, seed: 314
0.9151657223701
0.3925153017044
0.7007563710213
0.8806988000870
0.5301177501678
$ ./rng_gen 5 314 385
n: 5, blockSize: 385, nBlocks: 1, seed: 314
GPUassert: too many resources requested for launch rng_gen.cu 54
最后,如果这与我用于此初步测试的硬件有某种关系(该项目稍后将在功能更强大的机器上启动),以下是我使用的卡的规范:
./deviceQuery Starting...
CUDA Device Query (Runtime API) version (CUDART static linking)
Detected 1 CUDA Capable device(s)
Device 0: "Quadro NVS 160M"
CUDA Driver Version / Runtime Version 5.5 / 5.5
CUDA Capability Major/Minor version number: 1.1
Total amount of global memory: 256 MBytes (268107776 bytes)
( 1) Multiprocessors, ( 8) CUDA Cores/MP: 8 CUDA Cores
GPU Clock rate: 1450 MHz (1.45 GHz)
Memory Clock rate: 702 Mhz
Memory Bus Width: 64-bit
Maximum Texture Dimension Size (x,y,z) 1D=(8192), 2D=(65536, 32768), 3D=(2048, 2048, 2048)
Maximum Layered 1D Texture Size, (num) layers 1D=(8192), 512 layers
Maximum Layered 2D Texture Size, (num) layers 2D=(8192, 8192), 512 layers
Total amount of constant memory: 65536 bytes
Total amount of shared memory per block: 16384 bytes
Total number of registers available per block: 8192
Warp size: 32
Maximum number of threads per multiprocessor: 768
Maximum number of threads per block: 512
Max dimension size of a thread block (x,y,z): (512, 512, 64)
Max dimension size of a grid size (x,y,z): (65535, 65535, 1)
Maximum memory pitch: 2147483647 bytes
Texture alignment: 256 bytes
Concurrent copy and kernel execution: No with 0 copy engine(s)
Run time limit on kernels: Yes
Integrated GPU sharing Host Memory: No
Support host page-locked memory mapping: Yes
Alignment requirement for Surfaces: Yes
Device has ECC support: Disabled
Device supports Unified Addressing (UVA): No
Device PCI Bus ID / PCI location ID: 1 / 0
Compute Mode:
< Default (multiple host threads can use ::cudaSetDevice() with device simultaneously) >
deviceQuery, CUDA Driver = CUDART, CUDA Driver Version = 5.5, CUDA Runtime Version = 5.5, NumDevs = 1, Device0 = Quadro NVS 160M
Result = PASS
就是这样。欢迎就此事提供任何指导。谢谢!
编辑:
1) 添加了正确的 cuda error checking ,正如罗伯特所建议的那样。
2) 删除了 cudaMemset 行,反正没用。
3) 在没有“-G -g”标志的情况下编译并运行代码。
4)相应地更新了输出。
最佳答案
首先,当您在使用 CUDA 代码时遇到问题时,始终建议您执行正确的操作 cuda error checking .它会消除一定程度的头痛,可能会节省您一些时间,并且肯定会提高人们在此类网站上为您提供帮助的能力。
现在您发现了每个线程的寄存器问题。编译器在生成代码时会出于各种目的使用寄存器。每个线程都需要这些寄存器的补充来运行它的线程代码。当您尝试启动内核时,必须满足的要求之一是每个线程所需的寄存器数量乘以启动中请求的线程数量必须小于每个 block 可用的寄存器总数。请注意,每个线程所需的寄存器数量可能必须四舍五入到某个粒度分配增量。另请注意,请求的线程数通常会四舍五入到下一个更高的增量 32(如果不能被 32 整除),因为线程是在 32 的 warps 中启动的。还要注意最大寄存器每个 block 因计算能力而异,如您所示,可以通过 deviceQuery
示例检查此数量。正如您所发现的,某些命令行开关(如 -G
)会影响 nvcc 使用寄存器的方式。
要提前通知这些类型的资源问题,您可以使用额外的命令行开关编译您的代码:
nvcc -arch=sm_11 -Xptxas=-v -o mycode mycode.cu
-Xptxas=-v
开关将生成 ptxas 汇编程序(将中间 ptx 代码转换为 sass 汇编代码,即机器代码)的资源使用输出,包括每个线程所需的寄存器。请注意,在这种情况下,输出将按内核传递,因为每个内核可能都有自己的要求。您可以在 documentation 中获得有关 nvcc 编译器的更多信息。 .
作为一种粗略的解决方法,您可以在编译时指定一个开关,以将所有内核编译限制为最大寄存器使用数:
nvcc -arch=sm_11 -Xptxas=-v -maxrregcount=16 -o mycode mycode.cu
这将限制每个内核每个线程使用不超过 16 个寄存器。当乘以 512(cc1.x 设备的每个 block 的线程硬件限制)时,得到的值为 8192,这是您设备的每个线程 block 的总寄存器的硬件限制。
然而,上述方法很粗糙,因为它对程序中的所有内核应用了相同的限制。如果您想针对每次内核启动对其进行定制(例如,如果您的程序中的不同内核启动不同数量的线程),您可以使用启动边界方法,这在 here 中有描述。 .
关于CURAND - 设备 API 和种子,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19737812/
Sequelize 中有没有办法添加另一列,然后用另一列的内容填充它? 最佳答案 您可以使用迁移来做到这一点。 就像是 queryInterface.addColumn( 'MyAwesomeTa
如何计算info_hash参数?又名对应于信息字典的哈希?? 来自官方规范: info_hash The 20 byte sha1 hash of the bencoded form of the i
是否可以直接从数据库或服务等将 URL 获取到 Nutch。我对从数据库或服务获取数据并将其写入 Seed.txt 的方式不感兴趣. 最佳答案 没有。这不能直接使用默认的 nutch 代码库来完成。需
MessageDigest 类实现了 SHA-1 算法(以及许多其他算法)。 SHA-1 算法允许使用不同的“种子”或初始摘要。参见 SHA-1 Psuedocode 算法初始化变量,或种子: Ini
我想创建一个应用程序,其中登录密码可以作为伪随机数生成器的种子以重新创建加密 key 。然后,该加密 key 将用于加密发送到应用程序数据库和从应用程序数据库发送的所有数据,使用户数据甚至主机都无法访
这个问题在这里已经有了答案: Recommended way to initialize srand? (15 个答案) 关闭 8 年前。 使用 srand(time(NULL))似乎过于确定性。例
我在获取要在我的自定义数据库初始值设定项上调用的 Seed 方法时遇到问题。我正在使用 EF 5.0 并具有以下代码: public static class MyDatabase { pub
是否可以像在 Rails 中那样“播种”数据库?我想将种子与图像对象管理器结合使用,以便我可以按标题获取记录。 最佳答案 根据您对 Ingo 的回答留下的评论,您想将 requireDefaultRe
我现在设置了一个应用程序来使用 EF6 代码优先迁移。我使用 Add-Migration 的标准工作流程,然后在控制台中使用 Update-Database。我在本地以及我们的开发环境中使用 Migr
如果 Name 返回然后删除 first name Name john Age 30 Name Alice Name Travis Age 12 Name Monty Name Hannah 期望的输
在迁移完成后,是否可以在我的迁移中放入一些东西来自动为表播种测试数据? 或者您必须单独播种? 最佳答案 您可以使用 --seed 选项调用 migrate:refresh 以在迁移完成后自动播种: p
我正在尝试使用不同的种子生成 scipy.stats.pareto.rvs(b, loc=0, scale=1, size=1)。 在 numpy 中,我们可以使用 numpy.random.seed
我的种子有问题。这是我的表结构: 1.Complaints: Schema::create('complaints', function (Blueprint $table) {
我在使用数据库初始化程序时遇到问题 - 从未调用过种子方法。类似的代码在另一个项目中工作,所以我很困惑为什么他们这次不工作。 这是我的代码: RecipeContext.cs public c
我正在尝试做一些我认为非常简单的事情,只需使用 RAND 创建 0-1 之间的随机数,并将其分配给十进制变量。但每次我在 MySQL 中运行代码时,它都会返回零! 参见下面的代码: DELIMITER
我有一个问题...... 这里我们得到了一个二维字节数组: byte[][] duengonMap = new byte[500][500]; 因为我想将它从客户端发送到服务器或者相反,我需要将其放入
我尝试在我的计算机上运行 Angular-seed(Windows 10,上次更新)https://github.com/angular/angular-seed 。网络工作正常,但我的 Protra
我有一个随机过程的分布式过程。因此,我使用 numpy.random.RandomState 来播种数字。问题是我必须在包装器中使用另一个 numpy.random 函数。现在我失去了种子的再现性,因
我需要确保我程序中的所有随机性都是完全可复制的。我应该在哪里调用 random.seed()? 我认为它应该在我的 main.py 模块中,但它导入了碰巧使用随机函数的其他模块。 我可以仔细浏览我的导
首先尝试使用 Entity Framework 和代码在 ASP.NET 网络应用程序中植入数据。我将这段代码放在 Configuration.cs 文件的 Seed() 方法中。现在,我正在处理解决
我是一名优秀的程序员,十分优秀!