c ++多线程共享资源

时间:2013-06-28 17:01:00

标签: c++ multithreading boost

我正在尝试使用boost库多线程化一段代码。问题是每个线程都必须访问和修改几个全局变量。我正在使用互斥锁来锁定共享资源,但是当程序没有多线程时,程序最终需要花费更多时间。关于如何优化共享访问的任何建议?

非常感谢!

在下面的例子中,* choose_ecount *变量必须被锁定,我不能把它从循环中取出并锁定它只在循环结束时进行更新,因为它需要最新的值由内部功能。

for(int sidx = startStep; sidx <= endStep && sidx < d.sents[lang].size(); sidx ++){
    sentence s = d.sents[lang][sidx];
    int senlen = s.words.size();
    int end_symb = s.words[senlen-1].pos;

    inside(s, lbeta);
    outside(s,lbeta, lalpha);
    long double sen_prob = lbeta[senlen-1][F][NO][0][senlen-1];

    if (lambda[0] == 0){
        mtx_.lock();
        d.sents[lang][sidx].prob = sen_prob;
        mtx_.unlock();
    }

    for(int size = 1; size <= senlen; size++)
        for(int i = 0; i <= senlen - size ; i++)
        {
            int j = i + size - 1;
            for(int k = i; k < j; k++)
            {
                int hidx = i;   int head = s.words[hidx].pos;
                for(int r = k+1; r <=j; r++)
                {
                    int aidx = r;   int arg  = s.words[aidx].pos;
                        mtx_.lock();
                    for(int kids = ONE; kids <= MAX; kids++)
                    {
                        long double num = lalpha[hidx][R][kids][i][j] * get_choose_prob(s, hidx, aidx) *
                                lbeta[hidx][R][kids - 1][i][k] * lbeta[aidx][F][NO][k+1][j];
                        long double gen_right_prob = (num / sen_prob);

                        choose_ecount[lang][head][arg] += gen_right_prob; //LOCK
                        order_ecount[lang][head][arg][RIGHT] += gen_right_prob; //LOCK
                    }
                        mtx_.unlock();
                }

}

3 个答案:

答案 0 :(得分:1)

从您发布的代码中我只能看到对choose_ecount和order_ecount的写入。那么为什么不使用本地每线程缓冲区来计算总和,然后在最外层循环后添加它们并仅同步此操作?

编辑: 如果您需要访问choose_ecount的中间值,您如何确保存在正确的中间值?一个线程可能已完成其循环的2次迭代,同时在另一个线程中产生不同的结果。

听起来你需要使用屏障进行计算。

答案 1 :(得分:0)

在内循环中使用互斥锁不太可能获得可接受的性能。并发编程很难,不仅适用于程序员,也适用于计算机。现代CPU的很大一部分性能来自于能够将代码块视为独立于外部数据的序列。对单线程执行有效的算法通常不适合多线程执行。

你可能想看看boost::atomic,它可以提供无锁同步,但原子操作所需的内存障碍仍然不是免费的,所以你可能仍会遇到问题,你可能会必须重新考虑你的算法。

答案 2 :(得分:0)

我猜您将整个问题划分为从startStependStep的块,以便由每个线程进行处理。

由于你已经锁定mutex,所以你有效地序列化所有线程: 您将问题划分为一些块,这些块以串行但未指定的顺序处理。 这是你唯一得到的就是多线程的开销。

由于您在double上运行,因此使用原子操作不是您的选择:它们通常仅针对整数类型实现。

唯一可行的解​​决方案是遵循Kratz的建议,为每个线程提供choose_ecountorder_ecount的副本,并在线程完成后将它们减少为一个。