为何计算前10000整数和时单线程比多线程更快?附性能与计时疑问
单线程与多线程求和性能对比问题
代码实现
单线程版本
#include <stdio.h> #include <time.h> int main() { int sum = 0; clock_t start, end; double cpu_time_used; start = clock(); for (int i = 1; i <= 10000; i++) { sum += i; } end = clock(); cpu_time_used = ((double) (end - start)) / CLOCKS_PER_SEC; printf("Sum of first 10000 positive integers: %d\n", sum); printf("Time taken: %f seconds\n", cpu_time_used); return 0; }
4线程多线程版本
#include <stdio.h> #include <pthread.h> #include <time.h> #define NUM_THREADS 4 #define ARRAY_SIZE 10000 int sum = 0; int partialSums[NUM_THREADS] = {0}; void *calculateSum(void *threadid) { long tid; tid = (long)threadid; int chunkSize = ARRAY_SIZE / NUM_THREADS; int start = tid * chunkSize + 1; int end = (tid + 1) * chunkSize; for (int i = start; i <= end; i++) { partialSums[tid] += i; } pthread_exit(NULL); } int main() { pthread_t threads[NUM_THREADS]; int rc; long t; clock_t start, end; double cpu_time_used; start = clock(); for (t = 0; t < NUM_THREADS; t++) { rc = pthread_create(&threads[t], NULL, calculateSum, (void *)t); if (rc) { printf("ERROR; return code from pthread_create() is %d\n", rc); return -1; } } for (t = 0; t < NUM_THREADS; t++) { pthread_join(threads[t], NULL); } for (int i = 0; i < NUM_THREADS; i++) { sum += partialSums[i]; } end = clock(); cpu_time_used = ((double) (end - start)) / CLOCKS_PER_SEC; printf("Sum of first 10000 positive integers: %d\n", sum); printf("Time taken: %f seconds\n", cpu_time_used); pthread_exit(NULL); }
测试结果
单线程程序平均耗时0.000019秒,多线程程序约耗时0.0003秒。
问题与解答
1. 为何该场景下单线程比多线程更快?
多线程存在不可忽视的额外开销,在这个场景里完全盖过了并行计算的收益:
- 线程创建/销毁开销:操作系统创建线程需要分配栈空间、线程控制块等资源,销毁时还要回收,这些操作的耗时远超过10000次循环的计算量。
- 线程调度开销:多个线程切换时,操作系统要保存和恢复线程的寄存器、栈状态,带来上下文切换的消耗。
- 任务粒度太小:10000次循环拆分给4个线程,每个线程仅处理2500次循环,计算任务本身太轻量,根本抵消不了多线程的额外成本。
2. 多线程程序何时比单线程更具性能优势?
满足以下条件时,多线程能体现性能优势:
- 任务计算量足够大:单个线程的计算耗时远超过线程创建、调度的开销,并行计算的收益能覆盖额外成本。
- 存在可并行的逻辑:任务能拆分为多个独立子任务,子任务间依赖极少,不需要频繁同步。
- CPU有空闲核心:多线程依赖多核CPU,若核心已被占满,多线程只会增加调度开销,无法提升性能。
3. 哪些场景适合使用多线程?
- CPU密集型并行任务:比如大规模数据计算、矩阵运算、视频编码解码等,可拆分到多个核心同时执行,充分利用CPU资源。
- IO密集型任务:比如网络请求、文件读写,当一个线程等待IO完成时,其他线程可继续执行,避免CPU空闲。
- 高响应性程序:比如GUI应用,用单独线程处理界面渲染和用户输入,后台线程处理耗时操作,保证界面不卡顿。
- 批量处理任务:比如批量处理文件、批量发送请求,拆分任务到多线程并行处理,提升整体效率。
4. 如何准确对比程序的执行时间?(因听说clock函数在高负载环境下可能产生错误值)
要准确测量执行时间,可从以下几点优化:
- 使用墙钟时间:
clock()统计的是程序占用的CPU总时间,多线程场景下会累加所有线程的CPU时间,结果偏大。改用gettimeofday()(POSIX系统)或QueryPerformanceCounter()(Windows系统)获取墙钟时间,即程序从开始到结束的实际流逝时间。 - 多次取平均值:单次测量受系统负载影响大,建议重复运行程序多次(如1000次),去掉极值后取平均,减少误差。
- 隔离测试环境:测试时关闭无关程序,减少系统负载波动对结果的影响。
- 用专业性能工具:比如Linux的
perf、Intel的VTune等,不仅能准确测时间,还能分析程序瓶颈。
内容的提问来源于stack exchange,提问作者Geek
相关产品推荐
相关产品推荐

