多线程代码没有按预期工作



由于我对多线程的概念非常陌生,所以我试图保持事情非常简单。我在Visual Studio 2019中编写的完整程序如下试图比较单线程与同时运行的3个线程的性能。每个线程都有自己的数据要处理,所以我假设不需要对其他线程进行数据保护。

该算法只是创建斐波那契数列的前64个数字,并被重新创建数百万次。这个算法并没有实际用途。创建它只是为了浪费CPU时间。

在一个运行在2ghz的现代笔记本电脑上,一个单线程耗时7.6秒才能完成。不幸的是,有3个线程,大多数情况下将花费大约7秒才能完成。这比单个线程稍微好一点!但是偶尔3个线程将花费大约2.54秒才能完成。最后一次执行的时间是单个线程的1/3多一点,这是我预计大多数情况下会发生的情况。

我不知道这是怎么回事。但这似乎是某种形式的失速或同步问题。谢谢你的帮助。

#include <stdio.h>
#include <iostream>
#include <thread>
#include <chrono>
#define ITERATIONS 10000000
using namespace std;
using namespace std::chrono;
void WasteTime(__int64 fib[], int start, int end)
{
int i;

for (i = start; i < end; i++)
{
// Initialise the sequence
fib[0] = 1;
fib[1] = 1;

// Create Fibonacci sequence
for (int f1 = 0, f2 = 1, f3 = 2; f1 < 62; f1++, f2++, f3++)
{
fib[f3] = fib[f1] + fib[f2];
}
// Display iteration count
if (i % 0x1000000 == 0)
printf("%10un", i);
}
// Display final iteration count for thread
printf("%10un", i);
}
void WasteTimeUsingThreads(__int64 fib1[], __int64 fib2[], __int64 fib3[])
{
thread t1(WasteTime, fib1,               0, 10 * ITERATIONS);
thread t2(WasteTime, fib2, 10 * ITERATIONS, 20 * ITERATIONS);
thread t3(WasteTime, fib3, 20 * ITERATIONS, 30 * ITERATIONS);
// Before the main thread continues running, wait for all threads to finish.
t1.join();
t2.join();
t3.join();
}
int main()
{
__int64 fib1[64], fib2[64], fib3[64];
auto start = steady_clock::now();
WasteTime(fib1, 0, 30 * ITERATIONS);
auto end = steady_clock::now();
cout << "Time for normal way is: " << duration_cast<milliseconds>(end - start).count() << endl;
start = steady_clock::now();
WasteTimeUsingThreads(fib1, fib2, fib3);
end = steady_clock::now();
cout << "Time for multithreaded way is: " << duration_cast<milliseconds>(end - start).count() << endl;

return 0;
}

首先,您的fib1,fib2,fib3阵列很小,并且可能在现代处理器上共享相同的CPU缓存线(例如,2015年后设计的64位模式的一些英特尔或AMD)。所以你可能会有争论。阅读缓存一致性协议

您是否尝试使用大于页面大小的数组(在许多处理器上通常至少为4kb)?

确保在编译器中启用优化。对于GCC,至少使用g++ -O2编译。

你可以使用剖析工具,比如Linux的oprofile(1)

在我的Linux Ubuntu 21桌面(AMD Ryzen Threadripper 2970WX),我使用(与<stdint.h>头)#define ITERATIONS 20000000int64_t fib1[4096], fib2[4096], fib3[4096];作为局部变量,并与/usr/bin/g++-10 -std=c++11 -O2编译你的john.cc文件。产出:

Time for normal way is: 47255
Time for multithreaded way is: 16074

我也试着用/usr/bin/g++-11 -std=c++11 -O3 john.cc -o john -lstdc++ -lpthread编译,性能甚至更好:

Time for normal way is: 11714
Time for multithreaded way is: 3989

代码相同
int64_t fib1[128], fib2[128], fib3[128];

使用/usr/bin/g++-11 -std=c++11 -O1 john.cc -o john -lstdc++ -lpthread编译得到

Time for normal way is: 51973
Time for multithreaded way is: 17678

这与我的直觉是一致的。

最新更新