我正在编写一个可以解释为生产者/消费者模型的cuda程序。
有两个内核,一个在设备存储器上产生数据,
另一个内核是生成的数据。
消耗纱线的数量设置为经纱尺寸32的倍数的两倍。
并且每个经线等待直到已经产生了32个数据。
我这里有点问题。
如果消费者内核的加载晚于生产者,
程序不会停止。
即使先加载了consumer,程序有时也会无限期地运行。
我想问的是,在CUDA中有没有一个很好的生产者/消费者实现模型?
有人能给我一个方向或参考吗?
下面是我的代码框架。
**kernel1**:
while LOOP_COUNT
compute something
if SOME CONDITION
atomically increment PRODUCE_COUNT
write data into DATA
atomically increment PRODUCER_DONE
**kernel2**:
while FOREVER
CURRENT=0
if FINISHED CONDITION
return
if PRODUCER_DONE==TOTAL_PRODUCER && CONSUME_COUNT==PRODUCE_COUNT
return
if (MY_WARP+1)*32+(CONSUME_WARPS*32*CURRENT)-1 < PRODUCE_COUNT
process the data
if SOME CONDITION
set FINISHED CONDITION true
increment CURRENT
else if PRODUCUER_DONE==TOTAL_PRODUCER
if currnet*32*CONSUME_WARPS+THREAD_INDEX < PRODUCE_COUNT
process the data
if SOME CONDITION
set FINISHED CONDITION true
increment CURRENT发布于 2011-03-04 14:42:13
由于您没有提供实际的代码,因此很难检查bug在哪里。通常框架是正确的,但问题出在细节上。
我能想到的一个可能的问题:
默认情况下,在CUDA中,不能保证一个内核的全局内存写操作对另一个内核可见,原子操作除外。然后,您的第一个内核可能会递增PRODUCER_DONE,但数据中仍然没有数据。
幸运的是,您得到了内部函数__threadfence(),它会暂停当前线程的执行,直到数据可见。你应该把它放在原子递增PRODUCER_DONE之前。查看CUDA编程指南中的第B.5章。
另一个可能出现也可能不会出现的问题:
从kernel2的角度来看,编译器可能会推断出PRODUCE_COUNT,一旦读取,它就永远不会改变。编译器可以优化代码,使得一旦加载到寄存器中,它就重用它的值,而不是每次都查询全局内存。解决方案?使用volatile,或使用另一个原子操作读取值。
(编辑)第三期:
我忘了还有一个问题。在预费米卡(400系列之前的GeForce)上,一次只能运行一个内核。因此,如果您安排生产者在消费者之后运行,系统将在生产者内核开始执行之前等待消费者内核结束。如果您想同时运行这两个程序,请将这两个程序放入单个内核中,并使用基于某个块索引的If分支。
https://stackoverflow.com/questions/5189191
复制相似问题