从其他CUDA流中读取更新的内存

时间:2013-11-04 19:41:07

标签: c++ cuda nvidia cuda-streams

我试图在一个内核函数中设置一个标志,然后在另一个内核函数中读取它。基本上,我正在努力做到以下几点。

#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锁定。我现在做错了什么?

再次感谢。

1 个答案:

答案 0 :(得分:0)

允许编译器进行相当积极的优化。此外,Fermi器件上的L1高速缓存不保证是连贯的。要解决这些问题,请尝试将volatile关键字添加到flag变量的函数用法中,如下所示:

__global__ void set_flag(volatile int *flag)       

__global__ void read_flag(volatile int *flag)     

一般来说,当用于驻留在全局内存中的变量时,这将导致编译器发出绕过L1高速缓存的负载,并且通常也会阻止将这些变量优化到寄存器中。

我认为你会有更好的结果。

由于这些问题,您发布的代码可能会陷入僵局。因此,您所看到的观察可能实际上是操作系统(例如Windows TDR)中断您的程序。