C++:多线程:并行比顺序花费更多时间

问题描述 投票:0回答:1

我第一次在 MAC 上使用 C++ 中的线程。

下面是我的代码。 (我的代码背后的动机

#include <iostream>
#include <thread>
#include <chrono>

using namespace std;

using namespace chrono;

const long long maxLimit = 2e9;

void getEvenSum(long long &sum) {
    for(int i = 0 ; i <= maxLimit ; i+=2) {
        sum += i;
    }
}

void getOddSum(long long &sum) {
    for(int i = 1 ; i <= maxLimit ; i+=2) {
        sum += i;
    }
}

int main() {
    
    auto startTime = high_resolution_clock::now();
    
    long long evenSum = 0 , oddSum = 0;
    thread evenSumThread(getEvenSum, ref(evenSum));
    thread oddSumThread(getOddSum, ref(oddSum));

    evenSumThread.join();
    oddSumThread.join();

    auto endTime = high_resolution_clock::now();
    auto duration = duration_cast<microseconds>(endTime - startTime);

    cout << " final sum is " << evenSum << " " << oddSum << endl;

    cout << " time taken with thread :" << duration.count() / (long double)1e6 << endl;

    

    startTime = high_resolution_clock::now();
    
    evenSum = 0 , oddSum = 0;
    getEvenSum(evenSum);
    getOddSum(oddSum);

    endTime = high_resolution_clock::now();
    duration = duration_cast<microseconds>(endTime - startTime);

    cout << " final sum is " << evenSum << " " << oddSum << endl;

    cout << " time taken without thread " << duration.count() / (long double)1e6 << endl;

    return 0;

}

输出:

 final sum is 1000000001000000000 1000000000000000000
 time taken with thread :5.01665
 final sum is 1000000001000000000 1000000000000000000
 time taken without thread 2.83442

输出结果非常出乎意料。线程化需要 5 秒,非线程化需要 2.8 秒。怎么办!!!

我尝试过但失败的解决方案,

  1. g++ --std=c++11 file.cpp
  2. g++ --std=c++11 -O3 -s -DNDEBUG file.cpp
    (时间疯狂变化,但线程仍然需要更多时间)
  3. g++ --std=c++17 file.cpp
  4. g++ clang++ -std=c++11 file.cpp
    (出现错误,“CLANG”不存在)
  5. 尝试更改XCode->产品->方案->更改方案(不打开任何更改方案的菜单,死胡同)
  6. 以上命令我已在 VS code 以及 MAC 终端(iterm)中尝试过。我尝试将 VS code 构建从“DEBUG”更改为“RELEASE”,但这也没有帮助。

PS:当我上次在 Linux 中练习时(2 年前),相同的代码可以工作

c++ multithreading macos c++11
1个回答
0
投票

在最新的 gcc 和 clang 上,

-O3
两个函数都已完全优化,您可以通过将其参数声明为
volatile
来防止这种情况。

void getEvenSum(volatile unsigned long long& sum) {
    for (unsigned long long i = 0; i <= maxLimit; i += 2) {
        sum += i;
    }
}

这还将

int
转换为
unsigned long long
以避免有符号溢出,这是未定义的行为。

第二个问题现在是错误共享,解决这个问题的一种方法是将两个变量相互远离,或者将这些变量与缓存行边界对齐

    alignas(64) unsigned long long evenSum = 0;
    alignas(64) unsigned long long oddSum = 0;

这样您应该获得更快的线程版本代码。

© www.soinside.com 2019 - 2024. All rights reserved.