2010-05-27 173 views
1

這是我的第一個多線程實現,所以它可能是一個初學者的錯誤。線程處理每個第二行像素的渲染(因此所有渲染都在每個線程內處理)。如果線程分別渲染屏幕的上部分和下部分,問題依然存在。多線程光線跟蹤噪聲

兩個線程都從相同的變量中讀取,這是否會導致任何問題?從我所瞭解的只有寫入可能會導致併發問題...

可以調用相同的函數會導致任何併發問題嗎?再次,從我的理解,這不應該是一個問題...

兩次線程寫入同一個變量的唯一時間是保存計算的像素顏色。這存儲在一個數組中,但它們從不寫入該數組中的相同索引。這會導致問題嗎?

Multi-threaded rendered image (防止垃圾郵件阻止我直接發佈圖片..)

詩篇。我在這兩種情況下使用完全相同的實現,唯一的區別是爲渲染創建的單個線程與兩個線程。

+1

你能發表一些代碼嗎?沒有代碼,回答你的問題很可能需要一個水晶球。不幸的是,併發問題通常非常非常微妙...... – 2010-05-27 00:56:06

回答

6

兩個線程都從相同的變量中讀取,這會導致任何問題嗎?從我所瞭解的只有寫作會導致併發問題...

這應該沒問題。顯然,只要數據在兩個線程開始讀取之前被初始化並且在兩個線程完成之後被銷燬。

調用相同的函數會導致任何併發問題嗎?再次,從我所瞭解的這不應該是一個問題...

是的,沒有。如果沒有代碼太難分辨。這個函數做什麼?它是否依賴共享狀態(例如static變量,全局變量,單例...)?如果是的話,那肯定是個問題。如果沒有任何共享狀態,那麼你沒事。

兩個線程寫入同一個變量的唯一時間是保存計算的像素顏色。這存儲在一個數組中,但它們從不寫入該數組中的相同索引。這會導致問題嗎?

有時候可能。一個什麼樣的數組?如果sizeof(element) == sizeof(void*)可能是安全的,但C++標準在多線程中是靜音的,所以它不會強制你的編譯器強制你的硬件使其安全。有可能你的平臺在這裏咬你(例如64位機器和一個寫32位的線程,可能會覆蓋相鄰的32位值),但這並不罕見。通常你最好使用同步來確保。

您可以通過兩種方式解決這個問題:

  • 每個線程構建自己的數據,然後將其彙總,當他們完成。
  • 您可以使用mutex保護共享數據。

在我的答案,缺乏承諾的是什麼使多線程編程硬:P

例如,從 Intel® 64 and IA-32 Architectures Software Developer's Manuals,描述了不同的平臺如何gaurantee不同級別的原子性:

7.1 .1保證原子操作

Intel486處理器(以及更新的 處理器自)保證 以下基本mem ORY操作將 總是用原子進行:

  • 讀取或寫入的字節
  • 讀取或寫入一個16位的邊界
  • 閱讀上對齊的字或寫上32位對齊的雙字邊界

奔騰處理器(並且由於較新的 處理器)保證按照 附加存儲器操作 將總是被原子地進行:

  • 讀取或寫入的64位邊界上對齊四字
  • 16位訪問,以適應一個32位數據總線內的非高速緩存存儲器位置

P6系列處理器(而且由於新 處理器)保證 以下額外的內存操作 將始終原子進行:

  • 未對齊16,32和64位訪問以適應高速緩存行

訪問可高速緩衝存儲是跨越總線寬度,高速緩存行, 分裂內的高速緩存的存儲器 和頁邊界不保證由英特爾酷睿2雙核處理器原子, 英特爾凌動,英特爾酷睿雙核,奔騰M, 奔騰4,英特爾至強,P6家庭, 奔騰和英特爾486處理器。所述 英特爾Core 2 Duo,英特爾凌,英特爾 酷睿,奔騰M,奔騰4,英特爾 Xeon和P6系列處理器提供允許 外部存儲器子系統使 分裂存取原子 總線控制信號;但是, 未對齊的數據訪問將會嚴重影響 處理器的性能,因此應避免使用 。

1

我已經解決了這個問題,我通過爲每個線程分別建立數據,就像Stephen提出的那樣(不是void * size的元素)。感謝您提供非常詳細的答案!

+0

非常好,很高興你能解決問題! – Stephen 2010-05-31 13:12:34