生产者/消费者模型和并发内核

时间:2011-03-04 03:01:09

标签: cuda producer-consumer


我正在编写一个可以解释为生产者/消费者模型的cuda程序
有两个内核, 一个在设备存储器上产生数据,
和其他内核生成的数据
清点线程的数量设置为32的倍数,即经线大小 并且每个warp等待已生成32个数据
我在这里遇到了一些问题 如果消费者内核的加载时间晚于生产者,则 该计划不会停止 即使首先加载消费者,该程序有时也会无限运行
我要问的是,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

1 个答案:

答案 0 :(得分:2)

由于您没有提供实际代码,因此很难检查错误的位置。通常情节是正确的,但问题在于细节。

我能想到的一个可能的问题:

默认情况下,在CUDA中,不能保证一个内核写入的全局内存将被另一个内核可见,原子操作除外。然后,您的第一个内核会增加PRODUCER_DONE,但DATA中仍然没有数据。

幸运的是,您将获得内部函数__threadfence(),它会暂停当前线程的执行,直到数据可见。您应该在原子递增PRODUCER_DONE之前将其放入。查看CUDA编程指南中的B.5章节。

可能出现或未出现的另一个问题:

从kernel2的角度来看,编译器可能会扣除PRODUCE_COUNT,一旦读取,它就永远不会改变。编译器可以优化代码,以便一旦加载到寄存器中,它就会重用其值,而不是每次都查询全局内存。解?使用volatile,或使用其他原子操作读取值。

(编辑) 第三期:

我忘记了另外一个问题。在前费米卡(400系列之前的GeForce)上,您一次只能运行一个内核。因此,如果您将生产者安排在使用者之后运行,系统将等待使用者内核在生产者内核开始执行之前结束。如果您希望两者同时运行,请将两者放入单个内核并根据某些块索引具有if分支。