cog*_*ita 6 c performance multithreading gcc pthreads
我是多线程的新手,并尝试通过一个简单的程序来学习它,它将n加1并返回总和.在连续的情况下,对n = 1e5和2e5 main
调用该sumFrom1
函数两次; 在多线程情况下,使用两个线程创建,pthread_create
并在单独的线程中计算两个和.多线程版本比顺序版本慢得多(参见下面的结果).我在12-CPU平台上运行它,线程之间没有通信.
多线程:
Thread 1 returns: 0
Thread 2 returns: 0
sum of 1..10000: 50005000
sum of 1..20000: 200010000
time: 156 seconds
Run Code Online (Sandbox Code Playgroud)
顺序:
sum of 1..10000: 50005000
sum of 1..20000: 200010000
time: 56 seconds
Run Code Online (Sandbox Code Playgroud)
当我在编译中添加-O2时,多线程版本(9s)的时间小于顺序版本(11s)的时间,但不如我预期的那么多.我总是可以打开-O2标志,但我对未经优化的情况下多线程的低速感到好奇.它应该比顺序版慢吗?如果没有,我该怎么做才能让它更快?
代码:
#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;
}
Run Code Online (Sandbox Code Playgroud)
UPDATE1:
经过一段关于"虚假分享"的谷歌搜索(谢谢,@马丁詹姆斯!),我认为这是主要原因.有(至少)两种方法来解决它:
第一种方法是在两个结构之间插入一个缓冲区(Thanks,@ daslink):
my_struct_t si1;
char memHolder[4096];
my_struct_t si2;
Run Code Online (Sandbox Code Playgroud)
没有-O2,耗时从~156s减少到~38s.
第二种方法是避免经常更新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;
Run Code Online (Sandbox Code Playgroud)
没有-O2,耗时从~156s减少到~35s或~109s(它有两个峰值!我不知道为什么.).使用-O2时,耗时约8秒.
通过将您的代码修改为
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;
}
Run Code Online (Sandbox Code Playgroud)
现象消失。您遇到的问题:
int
数据类型是完全错误的。你的数字已经超出了金额。有符号类型的溢出是未定义的行为。你很幸运,它没有吃掉你的午餐。-O0
这样做的话,就会产生错误共享和类似的东西的所有影响。您的代码还观察到其他错误:
atoi
void*
time_t
为int
请在发布之前编译您的代码-Wall
。
归档时间: |
|
查看次数: |
1719 次 |
最近记录: |