concurrent_vector在parallel_fo(PPL)内部不起作用



下面有一个示例工作代码(使用并行模式库(ppl)的parallel_fo)。这里的主要问题是sqr<concurrent_vector>存储的值在每次执行中都会发生变化,但不应该!

我使用<concurrent_vector>用于随机访问,为什么它不起作用?

#include <iostream>
#include <ppl.h>
#include <concurrent_vector.h>
using namespace std;
using namespace concurrency;
const int a = 10, b = 30;
critical_section cs;
int main() {
    concurrent_vector< int > labels( a * b );
    concurrent_vector< int > sqr( 5 );
    // filling label vector
    for ( int y = 0; y < b; y++ ) {
        for ( int x = 0; x < a; x++ ) {
            if( x<2 && y>3 )
                labels[ a * y + x ] = 1;
            else if( x<30 && y<5 )
                labels[ a * y + x ] = 2;
            else if( x>5 && y>10 )
                labels[ a * y + x ] = 3;
            else if( x>2 && y>20 )
                labels[ a * y + x ] = 4;
        }
    }
    // printing
    for ( int y = 0; y < b; y++ ) {
        for ( int x = 0; x < a; x++ ) {
            cout << labels[ a * y + x ] << ", ";
        }
        cout << endl;
    }
    parallel_for ( 0, b, [ & ]( int y ) {
        for ( int x = 0; x < a; x++ ) {
            //cs.lock();  // when i used it's working but slow
            int i = labels[ a * y + x ];
            //cs.unlock();
            if ( i < 0 ) continue;
            sqr[ i ] ++;
        }
    } );
    for( int i=0; i<5; i++ )
        cout << sqr[i] << ", ";
    cout << "" << endl;
    system ("pause");
    return 0;
}

您没有使用任何与并发相关的并发向量特性。事实上,你可以用标准向量来代替它,没有任何区别。。。显然,在内核的每次执行中,i的值都是重叠的。绝对不能保证对向量的同一元素的并发写入是同步的。因此,您得到的结果是随机的——这只是非原子写入数据竞争的结果。

使用task_group::wait方法应该更快(因为您不必每次都锁定/解锁),而且它可能会如您所期望的那样工作。

此方法阻止当前任务,直到其他任务的任务为止小组已经完成了他们的工作。

请参阅MSDN:并行任务。

更新:我已经运行了一些定时测试,似乎这不是一个解决方案(此外,这两个测试都在双核上的大数据输入中失败)。这可能是concurrent_vector中的"design"错误,如英特尔的TBB-TBB::concurrent_vect返回错误大小的

最新更新