为什么我的多线程程序比单线程程序慢?
Why my multi thread program is slower than single thread program?
我知道很多人已经问过这个话题了,但我真的不明白为什么我的程序即使不计算标准输入和输出也很慢。
这是我的单线程程序。
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define LEN 30000
int **arr;
int main()
{
arr = malloc(sizeof(int *) * LEN);
for(int i=0;i<LEN;i++)
arr[i] = malloc(sizeof(int) * LEN);
clock_t st, ed;
st = clock();
for(int i=0;i<LEN;i++)
for(int j=0;j<LEN;j++)
arr[i][j] = 1;
ed = clock();
printf("time : %ld\n", ed-st);
}
这是我的多线程程序
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <time.h>
#define LEN 30000
int **arr;
void *thread_excute(void *thread_argv)
{
int start = ((int *)thread_argv)[0];
int height = ((int *)thread_argv)[1];
for(int i=0;i<height;i++)
for(int j=0;j<LEN;j++)
arr[start+i][j] = 1;
return 0;
}
int main()
{
arr = malloc(sizeof(int *) * LEN);
for(int i=0;i<LEN;i++)
arr[i] = malloc(sizeof(int) * LEN);
clock_t st, ed;
st = clock();
// thread = 4
pthread_t *thread_num = malloc(sizeof(int) * 4);
int **argv = malloc(sizeof(int *) * 4);
for(int t=0;t<4;t++)
{
argv[t] = malloc(sizeof(int) * 2);
argv[t][0] = t*(LEN/4);
argv[t][1] = LEN/4;
pthread_create(&thread_num[t], 0, thread_excute, (void *)argv[t]);
}
for(int t=0;t<4;t++)
pthread_join(thread_num[t], 0);
ed = clock();
printf("time : %ld\n", ed-st);
}
这是将 30000 * 30000 int 数组填充为 1 的程序。
我制作多线程程序,每个线程填充不同的数组行。
所以我猜想多线程程序会比单线程程序快。
但这是输出。
// single thread program
time : 3782958
// multi thread program
time : 3997991
我 运行 这个程序在 Ubuntu 20.04 上,我有 4 个 cpu 核心。
我通过 gcc file.c -o file -lpthread
编译这段代码
我不知道为什么会这样。
这是您的 multi-thread 程序的调整版本:
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define LEN 30000
int **arr;
void *thread_excute(void *thread_argv) {
// clock_t st, ed;
// st = clock();
int start = ((int *)thread_argv)[0];
int height = ((int *)thread_argv)[1];
int thread = ((int *)thread_argv)[2];
for(int i=start; i<start+height; i++)
for(int j=0;j<LEN; j++)
arr[i][j] = 1;
// ed = clock();
// printf("%d %ld %ld %ld\n", thread, st, ed, ed-st);
return 0;
}
int main(int argc, char *argv[]) {
arr = calloc(1, sizeof(int *) * LEN);
arr[0] = calloc(LEN, sizeof(int) * LEN);
for(int i=1; i<LEN; i++)
arr[i] = arr[0] + i * LEN;
clock_t st, ed;
unsigned threads = (argc == 2) ? atoi(argv[1]) : 4;
pthread_t *thread_num = malloc(sizeof(int) * threads);
st = clock();
int **argv2 = malloc(sizeof(int *) * threads);
for(int t=0; t<threads; t++) {
argv2[t] = malloc(sizeof(int) * 3);
argv2[t][0] = t * (LEN/threads);
argv2[t][1] = LEN/threads;
argv2[t][2] = t;
pthread_create(&thread_num[t], 0, thread_excute, (void *)argv2[t]);
}
for(int t=0; t<threads; t++)
pthread_join(thread_num[t], 0);
ed = clock();
printf("%ld\n", ed-st);
}
如果您使用 -O3
构建它并使用 (bash) 时间进行基准测试,我将无法再可靠地获得比单一版本更低的 multi-threaded 运行线程版本(4 核,8 超线程):
threads
clock
time (real)
time (sys)
single
352917
0m0.361s
0m0.089s
multi 1
365564
0m0.373s
0m0.273s
multi 2
524756
0m0.274s
0m0.430s
multi 4
774477
0m0.215s
0m0.589s
multi 8
1711224
0m0.331s
0m1.136s
我的结论是 clock()
不是衡量“慢”的好指标。在我们从 4 线程变为 8 线程之前,您的程序会越来越快(这台笔记本电脑有 4 个内核/8 个超线程)。另一个要点是,随着线程数量的增加,操作系统会做更多的工作来完成同样的事情。
我知道很多人已经问过这个话题了,但我真的不明白为什么我的程序即使不计算标准输入和输出也很慢。
这是我的单线程程序。
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define LEN 30000
int **arr;
int main()
{
arr = malloc(sizeof(int *) * LEN);
for(int i=0;i<LEN;i++)
arr[i] = malloc(sizeof(int) * LEN);
clock_t st, ed;
st = clock();
for(int i=0;i<LEN;i++)
for(int j=0;j<LEN;j++)
arr[i][j] = 1;
ed = clock();
printf("time : %ld\n", ed-st);
}
这是我的多线程程序
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <time.h>
#define LEN 30000
int **arr;
void *thread_excute(void *thread_argv)
{
int start = ((int *)thread_argv)[0];
int height = ((int *)thread_argv)[1];
for(int i=0;i<height;i++)
for(int j=0;j<LEN;j++)
arr[start+i][j] = 1;
return 0;
}
int main()
{
arr = malloc(sizeof(int *) * LEN);
for(int i=0;i<LEN;i++)
arr[i] = malloc(sizeof(int) * LEN);
clock_t st, ed;
st = clock();
// thread = 4
pthread_t *thread_num = malloc(sizeof(int) * 4);
int **argv = malloc(sizeof(int *) * 4);
for(int t=0;t<4;t++)
{
argv[t] = malloc(sizeof(int) * 2);
argv[t][0] = t*(LEN/4);
argv[t][1] = LEN/4;
pthread_create(&thread_num[t], 0, thread_excute, (void *)argv[t]);
}
for(int t=0;t<4;t++)
pthread_join(thread_num[t], 0);
ed = clock();
printf("time : %ld\n", ed-st);
}
这是将 30000 * 30000 int 数组填充为 1 的程序。 我制作多线程程序,每个线程填充不同的数组行。 所以我猜想多线程程序会比单线程程序快。 但这是输出。
// single thread program
time : 3782958
// multi thread program
time : 3997991
我 运行 这个程序在 Ubuntu 20.04 上,我有 4 个 cpu 核心。
我通过 gcc file.c -o file -lpthread
我不知道为什么会这样。
这是您的 multi-thread 程序的调整版本:
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define LEN 30000
int **arr;
void *thread_excute(void *thread_argv) {
// clock_t st, ed;
// st = clock();
int start = ((int *)thread_argv)[0];
int height = ((int *)thread_argv)[1];
int thread = ((int *)thread_argv)[2];
for(int i=start; i<start+height; i++)
for(int j=0;j<LEN; j++)
arr[i][j] = 1;
// ed = clock();
// printf("%d %ld %ld %ld\n", thread, st, ed, ed-st);
return 0;
}
int main(int argc, char *argv[]) {
arr = calloc(1, sizeof(int *) * LEN);
arr[0] = calloc(LEN, sizeof(int) * LEN);
for(int i=1; i<LEN; i++)
arr[i] = arr[0] + i * LEN;
clock_t st, ed;
unsigned threads = (argc == 2) ? atoi(argv[1]) : 4;
pthread_t *thread_num = malloc(sizeof(int) * threads);
st = clock();
int **argv2 = malloc(sizeof(int *) * threads);
for(int t=0; t<threads; t++) {
argv2[t] = malloc(sizeof(int) * 3);
argv2[t][0] = t * (LEN/threads);
argv2[t][1] = LEN/threads;
argv2[t][2] = t;
pthread_create(&thread_num[t], 0, thread_excute, (void *)argv2[t]);
}
for(int t=0; t<threads; t++)
pthread_join(thread_num[t], 0);
ed = clock();
printf("%ld\n", ed-st);
}
如果您使用 -O3
构建它并使用 (bash) 时间进行基准测试,我将无法再可靠地获得比单一版本更低的 multi-threaded 运行线程版本(4 核,8 超线程):
threads | clock | time (real) | time (sys) |
---|---|---|---|
single | 352917 | 0m0.361s | 0m0.089s |
multi 1 | 365564 | 0m0.373s | 0m0.273s |
multi 2 | 524756 | 0m0.274s | 0m0.430s |
multi 4 | 774477 | 0m0.215s | 0m0.589s |
multi 8 | 1711224 | 0m0.331s | 0m1.136s |
我的结论是 clock()
不是衡量“慢”的好指标。在我们从 4 线程变为 8 线程之前,您的程序会越来越快(这台笔记本电脑有 4 个内核/8 个超线程)。另一个要点是,随着线程数量的增加,操作系统会做更多的工作来完成同样的事情。