我是C++中多线程编程的新手。我写了一段简单的代码,将其粘贴在下面。
在两个线程中运行时,代码的完成速度仅比在单线程中运行时快。我遇到了其他类似的问题,但是它们是不同的,因为我没有共享资源,两个线程都需要访问这些资源来访问:
代码如下:
#include <iostream>
#include <thread>
#include <mutex>
#include <chrono>
using namespace std;
typedef unsigned long long ull;
ull oddSum = 0;
ull evenSum = 0;
void addOdd(){
for(int i = 1; i <= 1999999999; i++){
if(i % 2 == 1)
oddSum += i;
}
}
void addEven(){
for(int i = 1; i <= 1999999999; i++){
if(i % 2 == 0)
evenSum += i;
}
}
int main(){
auto startTime = std::chrono::high_resolution_clock::now();
//Two threads
std::thread t1(addEven); //launch the two threads to run
std::thread t2(addOdd);
t1.join();
t2.join(); //wait for both to finish
//One thread
//addEven();
//addOdd();
auto stopTime = std::chrono::high_resolution_clock::now();
auto elapsed = std::chrono::duration_cast<std::chrono::microseconds>(stopTime - startTime);
cout << "Odd Sum: " << oddSum << endl;
cout << "Even Sum: " << evenSum << endl;
cout << elapsed.count()/(double)1000000 << endl;
return 0;
}
当我使用单线程运行时,平均10次运行大约是 7.3秒。
当我使用两个线程运行时,平均10次运行大约是 6.8秒。
由于绝大多数时间都由函数中的循环占用,因此我相信并行运行两个线程(每个线程具有一个函数)将使运行时间减半。
注1 :我知道时间可能无法适本地减半,更有根据的猜测是两个线程的运行时间最长为5秒。我了解创建线程对象有其自身的开销。
注2 :也许我遗漏了一些东西,但是线程无法访问两者之间的任何共享位置。
任何想法都欢迎。我熟悉并发编程背后的理论,现在我才刚刚开始获得一些动手经验。我有一个4核的Intel i7。
最佳答案
当经常从不同线程访问变量时,应确保它们位于不同的缓存行(x86上为64字节宽)。
您可以通过对齐变量来做到这一点:
ull oddSum __attribute__((aligned(64))) = 0;
ull evenSum __attribute__((aligned(64))) = 0;
未能这样做会有效地序列化写入操作,因为一次只能由一个CPU修改高速缓存行。
在多线程情况下,对齐变量会使我的运行时间减少30%。
正如@walnut在他的评论中提到的,如果您的编译器支持C++ 17,则可以通过可移植的方式来完成:
#include <new>
alignas(std::hardware_destructive_interference_size) ull oddSum = 0;
alignas(std::hardware_destructive_interference_size) ull evenSum = 0;
关于c++ - 有两个线程的运行时间与一个线程的运行时间没有改善,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61219173/