前一阵子学习多线程编程时,发现了一些问题,写下这篇 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, &params[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 是不建议使用的一个输出函数.

更新于 阅读次数

请我喝[茶]~( ̄▽ ̄)~*

Nirvana 支付宝

支付宝