簡體   English   中英

在遞歸函數上的OpenMP並行化

[英]OpenMP parallelization on a recursive function

我正在嘗試使用並行化來提高繪制具有層次排序對象的3D場景的刷新率。 場景繪制算法首先遞歸地遍歷對象樹,並從中構建繪制場景所需的有序數據的有序數組。 然后它多次遍歷該數組以繪制對象/覆蓋等。從我讀到的OpenGL不是一個線程安全的API,我假設數組遍歷/繪圖代碼必須在主線程上完成,但我我想我可能能夠並行化填充數組的遞歸函數。 關鍵問題是必須按照對象在場景中出現的順序填充數組,因此所有將給定對象與數組索引相關聯的功能必須按正確的順序完成,但是一旦分配了數組索引,我可以使用工作線程填充該數組元素的數據(這不一定是一個簡單的操作)。 所以這是我想要的偽代碼。 我希望你能理解xml-ish線程的語法。

recursivepopulatearray(theobject)
{
  <main thread>
  for each child of theobject
  {
     assign array index
     <child thread(s)>
       populate array element for child object
     </child thread(s)>
     recursivepopulatearray(childobject)
  }
  </main thread>
}

那么,是否可以使用OpenMP執行此操作,如果是這樣,怎么做? 是否有其他並行化庫可以更好地處理這個問題?

附錄:為了回應Davide要求進一步澄清的請求 ,讓我詳細解釋一下。 讓我們說場景是這樣排序的:

-Bicycle Frame
  - Handle Bars 
  - Front Wheel
  - Back Wheel
-Car Frame
  - Front Left Wheel
  - Front Right Wheel
  - Back Left Wheel
  - Back Right Wheel

現在,這些對象中的每一個都有很多與之相關的數據,即位置,旋轉,大小,不同的繪圖參數等。另外,我需要在這個場景上進行多次傳遞才能正確繪制它。 一個通道繪制對象的形狀,另一個通道繪制描述對象的文本,另一個通道繪制對象之間的連接/關聯(如果有)。 無論如何,如果我必須多次訪問它,從這些不同的對象中獲取所有繪圖數據是相當慢的,所以我決定使用一個通道將所有數據緩存到一維數組中,然后實際所有繪圖傳遞只看數組。 問題在於,因為我需要以正確的順序進行OpenGL推送/彈出,所以數組必須處於代表樹層次結構的正確深度優先搜索順序中。 在上面的示例中,必須按如下方式對數組進行排序:

index 0: Bicycle Frame
index 1: Handle Bars 
index 2: Front Wheel
index 3: Back Wheel
index 4: Car Frame
index 5: Front Left Wheel
index 6: Front Right Wheel
index 7: Back Left Wheel
index 8: Back Right Wheel

因此,必須正確地序列化數組的順序,但是一旦我正確地分配了該順序,我就可以並行化數組的填充。 例如,一旦我將自行車框架分配給索引0並將把手桿分配給索引1,一個線程可以為自行車框架填充數組元素,而另一個線程則為句柄條填充數組元素。

好吧,我想澄清這一點,我已經回答了我自己的問題,所以感謝Davide。 所以我發布了自己的答案

我認為你應該更好地澄清你的問題(例如,什么必須連續完成,為什么)

OpenMP的(像其他許多並行庫)並不能保證在不同的並行部分將被執行的順序,因為他們是真正的並行(多核計算機上),如果不同的部分寫相同的數據可能存在競爭條件。 如果你的問題沒問題,你肯定可以使用它。

正如gbjbaanb所提到的 ,你可以很容易地做到這一點 - 它只需要一個pragma語句來並行化它。

但是,有幾點需要注意:

首先,你提到這里的訂單很重要。 如果您需要在展平層次結構時保留排序,那么並行化(在此級別)將會出現問題。 你可能會完全失去你的訂單。

此外,並行化遞歸函數存在許多問題。 舉一個極端的情況 - 假設你有一個雙核機器,你有一棵樹,每個“父”節點有4個孩子。 如果樹很深,你會非常非常快地“過度並行化”這個問題,通常會使事情變得更糟,而不是更好,性能更好。

如果您要這樣做,您應該放置一個級別參數,並且只能並行化前幾個級別。 以我的4個孩子每個父母為例,如果你並行化前兩個級別,你已經將它分成16個並行塊(從4個並行塊調用)。

從你提到的,我將這部分串行,而不是你提到的第二部分:

“然后它遍歷該數組多次繪制對象/疊加等。”

這聽起來像是一個理想的並行化地方。

要並行化子線程,只需在循環之前放置一個pragma:

#pragma omp parallel for
for (i=0; i < elements; i++) 
{
}

任務完成。

現在,你是對的,你不能讓任何線程庫以完全並行的方式在另一個之前做一點(顯然!),而openMP沒有'lock'或'wait'功能(它確實有''等待所有人完成“關鍵字 - 屏障”,它不是為了模擬一個線程庫而設計的,但它確實允許你在並行部分“外部”存儲值,並將某些部分標記為“僅單線程”(有序關鍵字)所以這可以幫助您在並行循環中分配索引,而其他線程正在分配元素。

看一下入門指南

如果您使用的是Visual C ++,則還需要在編譯器構建設置中設置/ omp標志。

這是一段應該有效的修改過的偽代碼。

populatearray(thescene)
{
  recursivepopulatearray(thescene)

  #pragma omp parallel for
  for each element in array
    populate array element based on associated object
}

recursivepopulatearray(theobject)
{
  for each childobject in theobject
  {
     assign array index and associate element with childobject
     recursivepopulatearray(childobject)
  }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM