前一阵子学习多线程编程时,发现了一些问题,写下这篇 blog 记录一下~作业是写一个计算 N 以内素数的程序,然后用不同的方式实现多线程.
# 1. 使用 clock () 统计时间
以下是串行代码:
#include <iostream> | |
#include <math.h> | |
#include <vector> | |
#include <time.h> | |
#define N 10000000 | |
using namespace std; | |
int main(int argc, const char * argv[]) { | |
clock_t one, two; | |
one = clock(); // 开始计时 | |
vector<int> primes; | |
for(int i=2; i<=N; i++){ | |
for(int j=2; j<=N; j++){ | |
if(i%j==0 ){ | |
break; | |
} | |
if(j>sqrt(i) ){ | |
primes.push_back(i); | |
cout<<i<<endl; | |
break; | |
} | |
} | |
} | |
two= clock(); // 结束计时 | |
cout << "总时间: " << (double)(two- one ) * 1000.0 / CLOCKS_PER_SEC << " ms" << endl; | |
return 0; | |
} |
使用 clock () 在串行程序中可以正常输出时间,但比较这样输出的时间,会发现并行的程序比串行的程序用的时间要长,并且线程越多时间越长.
后来经过研究,发现 clock () 函数统计的是 cpu 的时钟频率。在多核的计算机上,并行程序会分至多个 cpu, 而 clock () 统计的是 cpu 总的时钟频率,所以这样统计的时间并行程序是一定不会比串行快的,加上并行的开销,所以会造成线程越多,输出时间越长的现象.
# 2. 使用 gettimeofday () 统计时间
#include <iomanip> | |
#include <iostream> | |
#include <stdio.h> | |
#include <math.h> | |
#include <vector> | |
#include <unistd.h> | |
#include <stdlib.h> | |
#include <pthread.h> | |
#include <sys/time.h> | |
#define THREAD_NUM 10 | |
#define N 10000000 | |
using namespace std; | |
vector<int> primes; | |
pthread_mutex_t work_mutex; | |
void* thread_function(void* arg){ | |
for(int i=*(int*)arg; i<=N; i+=THREAD_NUM){ | |
for(int j=2; j<=N; j++){ | |
if(i%j==0&&i!=2){ | |
break; | |
} | |
if(j>sqrt(i) ){ | |
pthread_mutex_lock(&work_mutex); | |
primes.push_back(i); | |
// printf("%d\n",i); | |
cout<<i<<endl; | |
pthread_mutex_unlock(&work_mutex); | |
break; | |
} | |
} | |
} | |
pthread_exit(NULL); | |
} | |
int main(int argc, const char * argv[]) { | |
struct timeval start; | |
struct timeval end; | |
gettimeofday(&start,NULL); | |
int params[THREAD_NUM]; | |
pthread_t threads[THREAD_NUM]; | |
pthread_mutex_init(&work_mutex, NULL); | |
for(int i=0;i<THREAD_NUM;i++){ | |
params[i] = i+2; | |
} | |
for(int i=0;i<THREAD_NUM;i++){ | |
pthread_create(&(threads[i]), NULL, thread_function, ¶ms[i]); | |
} | |
for(int i=0;i<THREAD_NUM;i++){ | |
pthread_join(threads[i], NULL); | |
} | |
pthread_mutex_destroy(&work_mutex); | |
gettimeofday(&end,NULL); | |
double time_use=(end.tv_sec-start.tv_sec)*1000000+(end.tv_usec-start.tv_usec);// 微秒 | |
cout.setf(ios::fixed); | |
cout << "总时间: " << setprecision(3) << time_use / 1000 << "ms" << endl; | |
return 0; | |
} |
gettimeofday () 函数是根据系统时间来统计程序用时的,在统计多线程程序时并不会出现错误,这样统计下来的并行程序时间确实会比串行快.
# 3.cout 和 printf ()
在编程过程中发现,cout 不放入临界区中时,输出是乱的,会被其他线程打断。放入临界区中,cout 可以保持不背打断,但运行效率不如直接用 printf ().
cout 是一个线程不安全的方法,而 printf () 是线程安全的。而且各个线程的 cout 是同一个输出流,在并行时频繁中断会导致在多线程编程中,cout 是不建议使用的一个输出函数.