2013-04-18 98 views
1

我有一個循環,我使用OpenMP進行並行化。在這個循環中,我從文件中讀取一個三角形,並對這些數據執行一些操作。這些操作從每個三角形到另一個三角形都是獨立的,所以我認爲這很容易並行化,只要我將文件的實際讀取保留在關鍵部分。OpenMP共享文件處理程序

  • 順序三角形閱讀並不重要
  • 一些三角形閱讀而被丟棄很快,一些需要一些更多的工作算法(BBOX建設,...)
  • 我做二進制I/O
  • 使用C++ ifstream的* tri_data *
  • 我SSD上

ReadTriangle file.read調用測試這個(),並讀取12個浮點來回一個ifstream。

#pragma omp parallel for shared (tri_data) 
for(int i = 0; i < ntriangles ; i++) { 
    vec3 v0,v1,v2,normal; 
#pragma omp critical 
    { 
     readTriangle(tri_data,v0,v1,v2,normal); 
    } 
    (working with the triangle here) 
} 

現在,我觀察到的行爲是,啓用OpenMP後,整個過程更慢。 我在代碼中添加了一些定時器來跟蹤在I/O方法中花費的時間以及在循環本身中花費的時間。

沒有OpenMP的:

Total IO IN time  : 41.836 s. 
Total algorithm time : 15.495 s. 

對於OpenMP:

Total IO IN time  : 48.959 s. 
Total algorithm time : 44.61 s. 

我的猜測是,因爲閱讀是一個關鍵部分,線程只是等待海誓山盟使用文件處理程序完成,導致等待時間更長。

任何關於如何解決這個問題的指針?我的程序將真正受益於可以使用多個進程處理讀取三角形。我已經嘗試玩線程調度和相關的東西,但這似乎並沒有幫助很多在這種情況下。

由於我正在研究一種非核心算法,因此引入緩衝區來保存多個三角形並不是真正的選擇。

+1

如何讓一個線程執行所有IO並將三角形放入隊列或類似的東西,其他線程將三角形放入並處理它們? – Grizzly

回答

1

所以,我提出的解決方案是基於主/從戰略,其中:

  1. 主(線程0)執行所有的I/O
  2. 奴隸做了一些工作檢索數據

的僞代碼將改爲類似如下:

#include<omp.h> 

vector<vec3> v0; 
vector<vec3> v1; 
vector<vec3> v2; 
vector<vec3> normal; 

vector<int> tdone; 

int nthreads; 
int triangles_read = 0; 

/* ... */ 

#pragma omp parallel shared(tri_data) 
{ 
    int id = omp_get_thread_num(); 
    /* 
    * Initialize all the buffers in the master thread. 
    * Notice that the size in memory is similar to your example. 
    */ 
#pragma omp single 
    { 
    nthreads = omp_get_num_threads(); 
    v0.resize(nthreads); 
    v1.resize(nthreads); 
    v2.resize(nthreads); 
    normal.resize(nthreads); 
    tdone.resize(nthreads,1); 
    } 

    if (id == 0) { // Producer thread 

    int next = 1; 
    while(triangles_read != ntriangles) { 
     if (tdone[next]) { // If the next thread is free 
     readTriangle(tri_data,v0[next],v1[next],v2[next],normal[next]); // Read data and fill the correct buffer 
     triangles_read++; 
     tdone[next] = 0; // Set a flag for thread next to start working 
#pragma omp flush (tdone[next],triangles_read) // Flush it 
     } 
     next = next%(nthreads - 1) + 1; // Set next 
    } // while 

    } else { // Consumer threads 

    while(true ) { // Wait for work     
     if(tdone[id] == 0) { 
     /* ... do work here on v0[id], v1[id], v2[id], normal[id] ... */ 
     tdone[id] == 1; 
#pragma omp flush (tdone[id]) // Flush it 
     }  
     if(tdone[id] == 1 && triangles_read == ntriangles) break; // Work finished for all 
    } 

    } 
#pragma omp barrier 

} 

我不確定這對你是否有價值,但這無疑是一個很好的傳情!

+0

謝謝,夥計。很快就會試用,如果滿足我的需求,請將其標記爲答案。 –