2011-03-04 75 views
0


我正在寫一個可以解釋爲生產者/消費者模型的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 

回答

2

既然你沒有提供一個實際的代碼,這是很難檢查哪裏出了錯誤。通常情況是正確的,但問題在於細節。

其中之一,我能想到的可能的問題:

默認情況下,在CUDA沒有保證全局存儲器由一個內核寫入將是可見的另一個核心,以原子操作的一個例外。那麼可能發生的情況是,您的第一個內核增加了PRODUCER_DONE,但DATA中仍然沒有數據。

幸運的是,您將獲得內在函數__threadfence(),它會暫停當前線程的執行,直到數據可見。您應該在自動遞增PRODUCER_DONE之前放置它。查閱CUDA編程指南中的章節B.5。

可能可能不顯示或另一個問題:從視圖kernel2點

,編譯器可以扣除PRODUCE_COUNT,曾經看過,它永遠不會改變。編譯器可以優化代碼,以便一旦加載到寄存器中,它就會重新使用它的值,而不是每次查詢全局內存。解?使用volatile,或使用另一個原子操作讀取該值。

(編輯) 第三個問題:

我忘了一個多問題。在費米卡之前(400系列之前的GeForce),您一次只能運行一個內核。因此,如果您安排生產者在消費者之後運行,那麼在生產者內核開始執行之前,系統將等待消費者內核結束。如果你想讓它們同時運行,那麼把它們放到一個單獨的內核中,並且根據一些塊索引設置一個if-branch。

+0

謝謝你的回答! – superscalar 2011-03-04 07:00:59