2012-03-31 103 views
6

我正在尝试使用我正在使用的程序并得到以下问题。 如果多个线程需要在同一个矢量上读取/写入,但是矢量的不同元素会损失性能吗?我感觉这就是我的程序在对其进行平滑处理时几乎没有得到更快的原因。看看下面的代码:OpenMP中的共享向量

#include <vector> 

int main(){ 

    vector<double> numbers; 
    vector<double> results(10); 
    double x; 

    //write 10 values in vector numbers 
    for (int i =0; i<10; i++){ 
     numbers.push_back(cos(i)); 
    } 

#pragma omp parallel for \ 
    private(x) \ 
    shared(numbers, results) 
     for(int j = 0; j < 10; j++){ 

      x = 2 * numbers[j] + 5; 
#pragma omp critical // do I need this ? 
      { 
       results[j] = x;  
      } 
     } 

    return 0; 

} 

显然,实际的程序确实更加昂贵的操作,但这个例子应 只能说明我的问题。那么for循环可以快速完成并行,或者不同的线程必须等待对方,因为一次只有一个线程可以访问向量编号,尽管它们都读取了向量的不同元素?

与写操作相同的问题:我需要的关键编译或因为每个线程写入矢量结果的不同元素是没有问题? 我很高兴能得到每一个帮助,也很高兴知道是否有更好的方法来做到这一点(也许根本不使用向量,但简单的数组和指针等?) 我也读向量aren “T在某些情况下是线程安全的,建议使用指针:OpenMP and STL vector

非常感谢您的帮助!

回答

7

我想,大多数在多线程向量的问题是,如果它有调整,然后将其复制向量的全部内容复制到内存中的新位置(一个更大的分配块),如果你是哪个并行访问这个,然后你试着读取一个已经被删除的对象。

如果不调整您的磁盘阵列,然后我还从未有过并发读取任何问题(只要显然是我不写相同的元素两次)写入矢量

至于缺的性能提升,openmp临界区会将你的程序降低到与使用1个线程相同的程度(取决于在该临界区以外实际完成多少操作)

您可以删除临界区语句以上记)。

+0

他不调整向量的。 – eudoxos 2012-03-31 09:22:39

+0

@eudoxos我意识到,从代码片段,我只是想确保有人提到,特别是因为他提出了一个事实,即STL矢量某些条件下不会 – SirGuy 2012-03-31 12:43:23

+0

+1线程安全:它不会真的拿出在这里,但你必须记住特定向量的操作,如追加,调整大小等不是线程安全的,并可能会中断。但只要每个元素只由一个线程写入,只需操作矢量的元素就没有问题。 – 2012-03-31 15:35:14

5

你没有加速正是由于关键性sectino,这是多余的,因为相同的元素绝不会在同一时间进行修改。删除关键部分,它会工作得很好。

您可以通过调度策略发挥好,因为如果内存访问是不是线性的(这是你给的例子),线程可能缓存打(在同一高速缓存行写元素)。 OTOH如果元素的数量按照你的情况给出,并且循环中没有分支(因此它们将以大约相同的速度执行),static,这是默认的IIRC,无论如何应该工作得最好。

(顺便说一句,你可以声明x内循环,避免private(x)shared指令暗示IIRC(我从来没有使用过)。)

+0

+1;如果你没有调整大小或追加到矢量或者你有什么矢量,它只是一个1d数组,并且OpenMP非常擅长操作数组。至于静态,私有等,我认为“最佳实践”是使用默认(none),并将所有内容明确地私有或共享,只是为了明确,并且@eudoxos指出,在并行范围中定义了变量部分使它们隐含私有,然后跟随代码更容易一些。 – 2012-03-31 15:36:32

+0

嗨,感谢您的帮助。在循环中声明x是否真的更快(每个线程都会声明它,然后),而不是像上面那样在循环之前,还是它具有相同的性能,但更好看?这是什么意思,内存访问不是线性的,为什么这样呢? – user1304680 2012-04-01 19:08:24

+0

@ user1304680:声明是针对编译器的,它只是说你想拥有一些尺寸的内存并在后续代码中以某种方式调用它。我怀疑任何像样的,适度优化的编译器都会有所作为。非线性访问:我的意思是随机访问相邻内存区域中线程的元素。随后,RAM向CPU提供大块内存,该内存大于矢量项。如果2个内核访问附近的RAM块,它可能在同一个缓存行中,然后它们在hw级别同步,但会使其变慢。除非需要,否则不要担心。 – eudoxos 2012-04-02 11:54:17