2013-04-18 76 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

谢谢,伙计。很快就会试用,如果满足我的需求,请将其标记为答案。 –