c ++使用std库进行多线程处理:比预期慢

时间:2016-06-06 20:56:16

标签: c++ multithreading

我尝试使用std库,特别是线程库。 我们的想法是在有多线程和无多线程的情况下填充矩阵。我有8个核心。

void fillMatrix(int ID, std::vector<std::vector<double>> & lMatrix,int inThread){

    for (int i = 0; i < 10000; ++i){
        if (i % inThread == ID){
            for (int j = 0; j < 10000; ++j){
                lMatrix[i][j] = 123456.0;
            }
        }
    }

}


void testMT(int inThread){

    std::vector<std::thread> lPool;
    std::vector<std::vector<double>> lMatrix(10000, std::vector<double>(10000));

    for (int i = 0; i < inThread; ++i){
        lPool.push_back(std::thread(std::bind(&fillMatrix,i, lMatrix,inThread)));
    }

    for (std::thread & t : lPool){
        t.join();
    }
}

主要代码:

int main(){
    const clock_t begin_time1 = clock();
    testMT(1);
    std::cout << float(clock() - begin_time1) / CLOCKS_PER_SEC;
}

testMT(1)运行需要2.1秒,而testMT(8)需要7.032秒。

有什么想法吗? 感谢。

4 个答案:

答案 0 :(得分:5)

你有一个非常糟糕的 if 会减慢它。

在1个线程的情况下总是如此,但是在8个线程的情况下它是真的然后是假的假...是的。分支预测在这里失败。

将第一个for循环拆分/分割到每个线程要好得多。就像线程1执行矩阵的前1/8,线程2执行第二个1/8,依此类推。

类似的东西:

for(int i = 10000*ID/inThread; i< 10000*(ID+1)/inThread; ++i)

在ID = 0的情况下,循环将从0变为2500,ID = 1将从2500变为5000,依此类推。

答案 1 :(得分:4)

您的线程都在修改附近内存位置中的相同对象。这意味着内存的所有权必须不断地从线程到线程进行乒乓。

这不是线程的合理使用。如果你希望在众多线程同时紧密地操纵同一个对象时保持性能,则需要专业知识来处理虚假共享等事情。

答案 2 :(得分:4)

您的代码无法按您的意愿运行。线程运行后,您会注意到lMatrix的所有元素都未设置为123456.0。这是因为std::bind将向量复制到自身中,然后将其发送到线程。您需要在绑定调用中使用std::ref(lMatrix)才能使其正常工作并使用相同的矩阵。

更改

std::bind(&fillMatrix,i, lMatrix,inThread)

std::bind(&fillMatrix, i, std::ref(lMatrix), inThread)

因此,执行时间增加的很大一部分可能是由复制开销引起的;每次线程启动时进行10000 x 10000次分配和复制(然后是解除分配)。

答案 3 :(得分:0)

在某种程度上,这是一个非常重要的问题。

  • 多线程代码总是比单线程代码慢! (最好的情况是,你仍然需要支付启动和停止线程的费用)

  • 并发使事情变得更快(有时)。

您的目标是从并发中获得的收益超过使用线程的成本 - 并且具有如此重要的好处,以至于“代价”增加了代码的复杂性。此示例未达到该目标。