在OpenMP线程中降低性能

时间:2011-11-14 11:44:43

标签: c++ performance file openmp

我使用Intel Xeon x2(24内核)和Windows Server 2008 试图并行化我的c ++程序。这里的模板代码:

vector< string > files;
vector< vector< float > > data; 
...
data.resize( files.size() ); 

#pragma omp parallel for 
for (int i=0; i<files.size(); i++) { // Files count is about 3000
    FILE *f = fopen(files[i].c_str(), "rb"); 

    // every file is about 40 mb
    data[i].resize(someSize);
    fread(&data[i][0], sizeof(float), someSize, f); 

    fclose(f);
    ...
    performCalculations();  
}

CPU使用率仅为0到5% 当我插入而不是 fread(&amp; data [i] [0],sizeof(float),someSize,f)

for (int j=0; j<data.size(); j++) {
    data[i][j] = rand(); 
}

CPU使用率增加到100%。
我已经尝试过使用fstream和WinApi ReadFile,但它没有产生太大影响。

我做错了什么?我不相信磁盘读数会这么慢......

3 个答案:

答案 0 :(得分:6)

  

我不相信磁盘读数会这么慢......

然后你最好开始相信。与CPU相比,磁盘速度极慢。并行I / O通常仅在您从多个源(如单独的磁盘或网络连接)读取时才有帮助。它可以很好地解决延迟问题,但不能解决带宽问题。

尝试一次性读取所有数据,然后以并行循环方式处理它。

答案 1 :(得分:3)

磁盘读数无法并行化*:您是否有1个或24个CPU内核不会改变磁盘I / O吞吐量。

如果一次 performCalculations();调用比读取40 MB文件中一个的内容要快,那么就无需在多个CPU上进行并行化。您的程序执行受磁盘带宽的限制。你有没有测量过这个?

*:他们可以,但需要硬件。就像在多个CPU上并行执行需要实际的多CPU硬件一样,并行化磁盘I / O需要更多的磁盘I / O硬件。

答案 2 :(得分:1)

如果您使用的是传统硬盘,则不会有任何可见的加速,因为会有很多并发文件读取。 HDD主要无法处理此类当前文件读取。这就是为什么你只有0-5%的CPU使用率,这意味着大多数并行循环只是等待文件操作。 (请注意,只要多个文件读数位于不同的物理磁盘或盘片上,磁盘读数就可以并行化。)

有几种解决方案:

  1. 尝试使用可以支持更好的随机/并发访问的SSD。
  2. 虽然在此答案中解释所有内容并不容易,但请尝试使用 pipeline parallelism 。 OpenMP不适合流水线操作,但TBB支持易于使用的管道模板。 Pipeline允许文件读取步骤和其他计算步骤,因此您可以获得不错的加速。当然,应该有足够的计算。