我想在CUDA内核中调用类似usleep()
的内容。基本目标是使所有GPU核心休眠或忙碌数小时 - 这是我想为CUDA应用程序做的一些健全性检查的一部分。我这样做的尝试如下:
#include <unistd.h>
#include <stdio.h>
#include <cuda.h>
#include <sys/time.h>
__global__ void gpu_uSleep(useconds_t wait_time_in_ms)
{
usleep(wait_time_in_ms);
}
int main(void)
{
//input parameters -- arbitrary
// TODO: set these exactly for full occupancy
int m = 16;
int n = 16;
int block1D = 16;
dim3 block(block1D, block1D);
dim3 grid(m/block1D, n/block1D);
useconds_t wait_time_in_ms = 1000;
//execute the kernel
gpu_uSleep<<< grid, block >>>(wait_time_in_ms);
cudaDeviceSynchronize();
return 0;
}
当我尝试使用NVCC编译时出现以下错误:
error: calling a host function("usleep") from a __device__/__global__
function("gpu_uSleep") is not allowed
显然,我不允许在内核中使用usleep()
等主机函数。什么是一个很好的替代品?
答案 0 :(得分:20)
你可以旋转clock()或clock64()。 CUDA SDK concurrentKernels示例执行此操作:
__global__ void clock_block(clock_t *d_o, clock_t clock_count)
{
clock_t start_clock = clock();
clock_t clock_offset = 0;
while (clock_offset < clock_count)
{
clock_offset = clock() - start_clock;
}
d_o[0] = clock_offset;
}
我建议使用clock64()。 clock()和clock64()处于循环中,因此您必须使用cudaDeviceProperties()查询频率。频率可以是动态的,因此很难保证精确的自旋循环。
答案 1 :(得分:10)
您可以忙着等待clock()
的循环。
要等待至少10,000个时钟周期:
clock_t start = clock();
clock_t now;
for (;;) {
now = clock();
clock_t cycles = now > start ? now - start : now + (0xffffffff - start);
if (cycles >= 10000) {
break;
}
}
// Stored "now" in global memory here to prevent the
// compiler from optimizing away the entire loop.
*global_now = now;
注意:这是未经测试的。处理溢出的代码是由@Pedro从this answer借来的。有关clock()
如何工作的详细信息,请参阅他的答案和CUDA C编程指南4.2中的B.10部分。还有一个clock64()
命令。
答案 2 :(得分:3)
使用最新版本的 CUDA 以及具有 Compute Capability 7.0 或更高版本(Volta、Turing、Ampere 等)的设备,您可以使用 __nanosleep()
原语:
void __nanosleep(unsigned ns);
这消除了旧答案中建议的忙碌睡眠的需要。