我试图在一个内核函数中设置一个标志,然后在另一个内核函数中读取它。基本上,我正在努力做到以下几点。
#include <iostream>
#include <cuda.h>
#include <cuda_runtime.h>
#define FLAGCLEAR 0
#define FLAGSET 1
using namespace std;
__global__ void set_flag(int *flag)
{
*flag = FLAGSET;
// Wait for flag to reset.
while (*flag == FLAGSET);
}
__global__ void read_flag(int *flag)
{
// wait for the flag to set.
while (*flag != FLAGSET);
// Clear it for next time.
*flag = FLAGCLEAR;
}
int main(void)
{
// Setup memory for flag
int *flag;
cudaMalloc(&flag, sizeof(int));
// Setup streams
cudaStream_t stream0, stream1;
cudaStreamCreate(&stream0);
cudaStreamCreate(&stream1);
// Print something to let me know that we started.
cout << "Starting the flagging" << endl;
// do the flag test
set_flag <<<1,1,0,stream0>>>(flag);
read_flag <<<1,1,0,stream1>>>(flag);
// Wait for the streams
cudaDeviceSynchronize();
// Getting here is a painful process!
cout << "Finished the flagging" << endl;
// Clean UP!
cudaStreamDestroy(stream0);
cudaStreamDestroy(stream1);
cudaFree(flag);
}
我最终获得了第二次打印输出,但只有在计算机冻结15秒后,我才能同时获得两次打印输出。这些流应该并行运行,而不是让系统陷入困境。我究竟做错了什么?我该如何解决这个问题?
感谢。
修改
似乎通过添加volitile
解决了一个特殊情况,但现在已经破坏了其他东西。如果我在两个内核调用之间添加任何内容,系统将恢复旧的行为,即立即冻结和打印所有内容。通过在sleep(2);
和set_flag
之间添加read_flag
来显示此行为。此外,当放入另一个程序时,这会导致GPU锁定。我现在做错了什么?
再次感谢。
答案 0 :(得分:0)
允许编译器进行相当积极的优化。此外,Fermi器件上的L1高速缓存不保证是连贯的。要解决这些问题,请尝试将volatile
关键字添加到flag
变量的函数用法中,如下所示:
__global__ void set_flag(volatile int *flag)
和
__global__ void read_flag(volatile int *flag)
一般来说,当用于驻留在全局内存中的变量时,这将导致编译器发出绕过L1高速缓存的负载,并且通常也会阻止将这些变量优化到寄存器中。
我认为你会有更好的结果。
由于这些问题,您发布的代码可能会陷入僵局。因此,您所看到的观察可能实际上是操作系统(例如Windows TDR)中断您的程序。