Parallel processing pthread的使用增加了执行时间,建议改进

Parallel processing pthread的使用增加了执行时间,建议改进,parallel-processing,pthreads,mutex,latency,Parallel Processing,Pthreads,Mutex,Latency,我有一段代码,看起来像这样 for(i=0;i<NumberOfSteps;i++) { for(k=0;k<NumOfNodes;k++) { mark[crawler[k]]++; r = rand() % node_info[crawler[k]].num_of_nodes; crawler[k] = (int)DataBlock[node_info[crawler[k]].index+r][0]; }

我有一段代码,看起来像这样

 for(i=0;i<NumberOfSteps;i++)
{
    for(k=0;k<NumOfNodes;k++)
    {

        mark[crawler[k]]++;
        r = rand() % node_info[crawler[k]].num_of_nodes;
        crawler[k] = (int)DataBlock[node_info[crawler[k]].index+r][0];
    }
}
for(i=0;i<NumberOfSteps;i++)
{
    for(k=0;k<NumOfNodes;k++)
    {            
        pthread_mutex_lock( &mutex1 );
        mark[crawler[k]]++;
        pthread_mutex_unlock( &mutex1 );

        pthread_mutex_lock( &mutex1 );
        r = rand() % node_info[crawler[k]].num_of_nodes;
        pthread_mutex_unlock( &mutex1 );

        pthread_mutex_lock( &mutex1 );
        crawler[k] = (int)DataBlock[node_info[crawler[k]].index+r][0];
        pthread_mutex_unlock( &mutex1 );
   }
}

for(i=0;i除了循环头之外,没有并行化任何东西。锁定和解锁之间的所有操作都必须按顺序执行。而且,由于锁定/解锁是(可能)昂贵的操作,因此代码变得越来越慢

要解决这个问题,您至少应该将昂贵的计算(没有互斥保护)与访问共享数据区域(使用互斥)分开,然后尝试将互斥移出内部循环

您可以使用原子增量指令(取决于平台),而不是普通的“++”,后者通常比互斥体便宜。但请注意,在并行处理来自不同线程的单个缓存线的数据时,不要经常这样做(请参阅)

AFAICS,您可以按照如下所示重写算法,而不需要互斥体和原子增量。如果numofodes是NumOfThreads的整数倍,则getFirstK()是numofodes/NumOfThreads*t

for(t=0;t<NumberOfThreads;t++)
{
    kbegin = getFirstK(NumOfNodes, NumOfThreads, t);
    kend   = getFirstK(NumOfNodes, NumOfThreads, t+1);

    // start the following in a separate thread with kbegin and kend 
    // copied to thread local vars kbegin_ and kend_

    int k, i, r;
    unsigned state = kend_; // really bad seed

    for(k=kbegin_;k<kend_;k++)
    {
        for(i=0;i<NumberOfSteps;i++)
        {
            mark[crawler[k]]++;
            r = rand_r(&state) % node_info[crawler[k]].num_of_nodes;
            crawler[k] = (int)DataBlock[node_info[crawler[k]].index+r][0];
        }
    }
}
// wait for threads/jobs to complete

用于(t=0;单独设置互斥锁本身并不能使代码并行。您需要创建多个线程,并为它们分配工作。创建线程的开销以及强制互斥的互斥锁/解锁的开销非常大。请考虑以线程可以尽可能长时间工作的方式对工作进行分区e独立-无需同步。我使用pthread_create();生成了多个线程。我不认为有互斥锁会使代码并行化。但这些线程必须跨越边界并在同一组变量上工作。对于
I
(外部循环)或
k
(内部循环),您并行化哪个循环或者两者都有?您最好描述一下如何用pthread并行化您的代码。(我不能肯定,但是
mutex1
lock/unlock实际上可能没有必要…)上面显示的整个代码都在一个函数中。我创建了多个线程来并行执行该函数。我之所以使用互斥体,是因为所有线程都共用elments、mark、DataBlock和node_info。外部for循环无法并行化,因为每个循环本质上都是通过图和内部循环的爬网是实际的爬网。整个爬网过程是跨进程拆分的。
rand()
不好,因为它修改了共享全局状态(共享源)。最好将
drand48
生成器与私有状态一起使用,即
erand48(3)
库函数。