[英]Why is multithreading slower than sequential programming in my case?
I'm new to multithreading and try to learn it through a simple program, which adds 1 to n and return the sum.我是多线程的新手,并尝试通过一个简单的程序来学习它,该程序将 1 添加到 n 并返回总和。 In the sequential case, the
main
call the sumFrom1
function twice for n = 1e5 and 2e5;在顺序情况下,对于 n = 1e5 和 2e5,
main
两次调用sumFrom1
function; in the multithreaded cases, two threads are created using pthread_create
and two sums are calculated in separate thread.在多线程情况下,使用
pthread_create
创建两个线程,并在单独的线程中计算两个总和。 The multithreadting version is much slower than the sequential version (see results below).多线程版本比顺序版本慢得多(见下面的结果)。 I run this on a 12-CPU platform and there are no communication between threads.
我在 12-CPU 平台上运行它,线程之间没有通信。
Multithreaded:多线程:
Thread 1 returns: 0
Thread 2 returns: 0
sum of 1..10000: 50005000
sum of 1..20000: 200010000
time: 156 seconds
Sequential:顺序:
sum of 1..10000: 50005000
sum of 1..20000: 200010000
time: 56 seconds
When I add -O2 in compilation, the time of multithreaded version (9s) is less than that of sequential version (11s), but not much as I expect.当我在编译中添加-O2时,多线程版本的时间(9s)比顺序版本的时间(11s)少,但没有我预期的多。 I can always have the -O2 flag on but I'm curious about the low speed of multithreading in the unoptimized case.
我总是可以打开-O2标志,但我对未优化情况下多线程的低速感到好奇。 Should it be slower than sequential version?
它应该比顺序版本慢吗? If not, what can I do to make it faster?
如果没有,我该怎么做才能让它更快?
The code:代码:
#include <stdio.h>
#include <pthread.h>
#include <time.h>
typedef struct my_struct
{
int n;
int sum;
}my_struct_t;
void *sumFrom1(void* sit)
{
my_struct_t* local_sit = (my_struct_t*) sit;
int i;
int nsim = 500000; // Loops for consuming time
int j;
for(j = 0; j < nsim; j++)
{
local_sit->sum = 0;
for(i = 0; i <= local_sit->n; i++)
local_sit->sum += i;
}
}
int main(int argc, char *argv[])
{
pthread_t thread1;
pthread_t thread2;
my_struct_t si1;
my_struct_t si2;
int iret1;
int iret2;
time_t t1;
time_t t2;
si1.n = 10000;
si2.n = 20000;
if(argc == 2 && atoi(argv[1]) == 1) // Use "./prog 1" to test the time of multithreaded version
{
t1 = time(0);
iret1 = pthread_create(&thread1, NULL, sumFrom1, (void*)&si1);
iret2 = pthread_create(&thread2, NULL, sumFrom1, (void*)&si2);
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
t2 = time(0);
printf("Thread 1 returns: %d\n",iret1);
printf("Thread 2 returns: %d\n",iret2);
printf("sum of 1..%d: %d\n", si1.n, si1.sum);
printf("sum of 1..%d: %d\n", si2.n, si2.sum);
printf("time: %d seconds", t2 - t1);
}
else // Use "./prog" to test the time of sequential version
{
t1 = time(0);
sumFrom1((void*)&si1);
sumFrom1((void*)&si2);
t2 = time(0);
printf("sum of 1..%d: %d\n", si1.n, si1.sum);
printf("sum of 1..%d: %d\n", si2.n, si2.sum);
printf("time: %d seconds", t2 - t1);
}
return 0;
}
UPDATE1:更新1:
After a little googling on "false sharing" (Thanks, @Martin James,).在谷歌搜索“虚假分享”后(谢谢,@Martin James,)。 I think it is the main cause: There are (at least) two ways to fix it:
我认为这是主要原因:有(至少)两种方法可以修复它:
The first way is inserting a buffer zone between the two structs (Thanks, @dasblinkenlight):第一种方法是在两个结构之间插入一个缓冲区(感谢 @dasblinkenlight):
my_struct_t si1;
char memHolder[4096];
my_struct_t si2;
Without -O2 , the time consuming decreases from ~156s to ~38s.没有-O2 ,耗时从 ~156s 减少到 ~38s。
The second way is avoiding frequently updating sit->sum
, which can be realized using a temp variable in sumFrom1
(as @Jens Gustedt replied):第二种方法是避免频繁更新
sit->sum
,这可以使用sumFrom1
中的临时变量来实现(正如@Jens Gustedt 回复的那样):
for(int sum = 0, j = 0; j < nsim; j++)
{
sum = 0;
for(i = 0; i <= local_sit->n; i++)
sum += i;
}
local_sit->sum = sum;
Without -O2 , the time consuming decreases from ~156s to ~35s or ~109s (It has two peaks. I don't know why.).没有-O2 ,耗时从 ~156s 减少到 ~35s 或 ~109s(它有两个峰值。我不知道为什么。)。 With -O2 , the time consuming stays ~8s.
使用-O2 ,耗时保持在 8 秒左右。
By modifying your code to通过将代码修改为
typedef struct my_struct
{
size_t n;
size_t sum;
}my_struct_t;
void *sumFrom1(void* sit)
{
my_struct_t* local_sit = sit;
size_t nsim = 500000; // Loops for consuming time
size_t n = local_sit->n;
size_t sum = 0;
for(size_t j = 0; j < nsim; j++)
{
for(size_t i = 0; i <= n; i++)
sum += i;
}
local_sit->sum = sum;
return 0;
}
the phenomenon disappears.现象消失。 The problems you had:
你遇到的问题:
int
as a datatype is completely wrong for such a test.int
作为数据类型是完全错误的。 Your figures where such that the sum overflowed.-O0
are really done as such, with all the implications of false sharing and stuff like that.-O0
的情况下确实是这样完成的,具有错误共享和类似内容的所有含义。 Your code also observed other errors:您的代码还观察到其他错误:
atoi
atoi
缺少包含void*
void*
time_t
as int
time_t
打印为int
Please compile your code with -Wall
before posting.请在发布前使用
-Wall
编译您的代码。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.