文档章节

OpenMp多线程编程计时问题

Gaussic
 Gaussic
发布于 2015/10/09 22:45
字数 1023
阅读 928
收藏 4

在做矩阵乘法并行化测试的时候,在利用<time.h>的clock()计时时出现了一点问题。

首先看串行的程序:

// matrix_cpu.c
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define NUM 2048

void matrixMul(float *A, float *B, float *C, int M, int K, int N)
{
    int i, j, k;
    for(i = 0; i < M; i++)
    {
        for(j = 0; j < N; j++)
        {
            float sum = 0.0f;
            for(k = 0; k < K; k++)
            {
                sum += A[i*k+k] * B[k*N+j];
            }
            C[i*N+j] = sum;
        }
    }
}

int main(int argc, char* argv[])
{
    float *A, *B, *C;
    clock_t start, finish;
    double duration;

    A = (float *) malloc (sizeof(float) * NUM * NUM);
    B = (float *) malloc (sizeof(float) * NUM * NUM);
    C = (float *) malloc (sizeof(float) * NUM * NUM);
    memset(A, 0, sizeof(float) * NUM * NUM);
    memset(B, 0, sizeof(float) * NUM * NUM);
    memset(C, 0, sizeof(float) * NUM * NUM);
    
    printf("Start...\n");

    start = clock();
    matrixMul(A, B, C, NUM, NUM, NUM);
    finish = clock();
    
    duration = (double)(finish - start) / CLOCKS_PER_SEC;
    printf("Time: %fs\n", duration);
    return 0;
}

在编译后,运行该程序,得到如下结果:

[wfshen@cu05 matrix]$ ./matrix_cpu
Start...
Time: 26.130000s

由于CPU是至强E5-2650,所以算得比较快(但目前仍然是串行,也就是说单核单线程),这样也要26秒了(在博主的i5-4200 ThinkPad上用时是171秒)。

加上time命令再运行一遍,结果如下:

[wfshen@cu05 matrix]$ time ./matrix_cpu
Start...
Time: 26.770000s

real	0m28.073s
user	0m26.779s
sys	0m0.019s

可以看到,时间与程序中统计的差不多,实际执行时间由于加了malloc等的时间所以长了一点,但还是合情合理的。


那么,再来看并行的OpenMP程序:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define NUM 2048
#define THREAD_NUM 2

void matrixMul(float *A, float *B, float *C, int M, int K, int N)
{
    int i, j, k;
#pragma omp parallel for private(j,k) num_threads(THREAD_NUM)
    for(i = 0; i < M; i++)
    {
        for(j = 0; j < N; j++)
        {
            float sum = 0.0f;
            #pragma ivdep
            for(k = 0; k < K; k++)
            {
                sum += A[i*k+k] * B[k*N+j];
            }
            C[i*N+j] = sum;
        }
    }
}

int main(int argc, char* argv[])
{
    float *A, *B, *C;
    clock_t start, finish;
    double duration;

    A = (float *) malloc (sizeof(float) * NUM * NUM);
    B = (float *) malloc (sizeof(float) * NUM * NUM);
    C = (float *) malloc (sizeof(float) * NUM * NUM);
    memset(A, 0, sizeof(float) * NUM * NUM);
    memset(B, 0, sizeof(float) * NUM * NUM);
    memset(C, 0, sizeof(float) * NUM * NUM);

    printf("Start...\n");

    start = clock();
    matrixMul(A, B, C, NUM, NUM, NUM);
    finish = clock();

    duration = (double)(finish - start) / CLOCKS_PER_SEC;
    printf("Time: %fs\n", duration);
    return 0;
}

可以看到,该OpenMP程序只使用了两个线程,那么运行时间理论上来说能减半。

在编译后,运行该程序,得到如下结果:

[wfshen@cu05 matrix]$ ./matrix_omp
Start...
Time: 26.550000s

这就奇怪了,明明心里面数了一下大概花了15秒,但是为什么计时还是26秒呢?

再加上time命令运行一遍:

[wfshen@cu05 matrix]$ time ./matrix_omp
Start...
Time: 26.440000s

real	0m13.438s
user	0m26.457s
sys	0m0.016s

可以看到,实际的运行时间是13秒,但是user却超过了13秒,且几乎是real的两倍。

查了一下,发现了这样的解释:

real: 墙上时间,即程序从开启到结束的实际运行时间
user: 执行用户代码所花的实际时间(不包括内核调用),指进程执行所消耗的实际CPU时间
sys:该程序在内核调用上花的时间

 在,单线程串行的时候,只有一个线程在运行,那么user所代表的就是一个cpu的时间。然而,当到多线程的情况下,一个进程可能有多个线程并行执行,但是user把所有的线程时间都加起来了,也就是算了一个总时间,这样,user的时间也就基本上等于单线程时的user时间。

这样,我们把线程数调到4,再运行代码(大概7秒):

[wfshen@cu05 matrix]$ ./matrix_omp
Start...
Time: 27.270000s
[wfshen@cu05 matrix]$ time ./matrix_omp
Start...
Time: 27.170000s

real	0m7.486s
user	0m27.176s
sys	0m0.018s

可以发现,实际运行时间7秒,CPU总时间27秒,差不多:

再把线程数调到16,再运行代码(大概2秒多):

[wfshen@cu05 matrix]$ ./matrix_omp
Start...
Time: 33.980000s
[wfshen@cu05 matrix]$ time ./matrix_omp
Start...
Time: 33.530000s

real	0m2.241s
user	0m33.479s
sys	0m0.075s

可以发现,CPU总时间有增加的趋势,不过实际时间还是大有减少。E5-2650是8核心16线程,再往上加线程时间反而会增长。


总结:在多线程的情况下,还是用time命令看时间吧。

© 著作权归作者所有

共有 人打赏支持
Gaussic
粉丝 399
博文 28
码字总数 66971
作品 0
宝山
私信 提问
多核编程框架 OpenMP 4.0 规范发布

OpenMP 4.0 规范发布了,这是 OpenMP 标准语言规范的一次主要的升级,除了很多主要增强外,该版本还提供了全新的机制用来描述数据和计算在不同计算机之间移动的代码。此外该版本新增对加速器...

oschina
2013/07/25
3.5K
3
Open MP 模板库20090405发布

OpenMP是由OpenMP Architecture Review Board牵头提出的,并已被广泛接受的,用于共享内存并行系统的多线程程序设计的一套指导性注释(Compiler Directive)。OpenMP支持的编程语言包括C语言、...

老枪
2009/04/05
1K
0
clang/llvm 已经完全实现 OpenMP 3.1 支持

OpenMP 3.1 在 clang/llvm 编译器上的功能完全实现!OpenMP 3.1标准于2011年获得批准,它支持几乎所有的跨核和多处理器系统,并且有良好的性能与可移植性。 OpenMP 是由 OpenMP Architectur...

oschina
2015/05/12
4K
18
OpenMP 4.5 发布,多核编程框架

OpenMP 4.5 发布了,OpenMP是由OpenMP Architecture Review Board牵头提出的,并已被广泛接受的,用于共享内存并行系统的多线程程序设计的一套编译指令 (Compiler Directive)。OpenMP支持的编...

oschina
2016/03/27
4.3K
7
VS2010环境与OpenMP远程多线程访问MySQL数据库的限制和困惑

本地的C++代码,打开OpenMP编译选项得到debug/release版本的可执行程序A.exe,A.exe是一个socket监听服务,监听端口port的请求。A接收到请求会创建一个新的线程t去调用B.dll中的算法完成计算...

liuyan
2012/08/06
719
0

没有更多内容

加载失败,请刷新页面

加载更多

开源软件会被云杀死吗 ?

本文转载云头条,原作者:Michael Stiefel是Reliable Software公司的负责人,是一名软件架构和开发顾问。 文章要点 虽然开源开发不会消失,但商业开源厂商的未来不是很有希望。随着全面管理的...

linuxCool
24分钟前
0
0
OSChina 周三乱弹 —— 谈什么对象?睡什么觉?

Osc乱弹歌单(2018)请戳(这里) 【今日歌曲】 @胖达panda :最肯忘却古人诗,最不屑一顾是相思。分享童丽的单曲《红豆生南国》: 《红豆生南国》- 童丽 手机党少年们想听歌,请使劲儿戳(这...

小小编辑
28分钟前
43
4
stylus

stylus基础教程,stylus实例教程,stylus语法总结

miaojiangmin
今天
3
0
PHP生成CSV之内部换行

当我们使用PHP将采集到的文件内容保存到csv文件时,往往需要将采集内容进行二次过滤处理才能得到需要的内容。比如网页中的换行符,空格符等等。 对于空格等处理起来都比较简单,这里我们单独...

豆花饭烧土豆
今天
2
0
使用 mjml 生成 thymeleaf 邮件框架模板

发邮件算是系统开发的一个基本需求了,不过搞邮件模板实在是件恶心事,估计搞过的同仁都有体会。 得支持多种客户端 支持响应式 疼彻心扉的 outlook 多数客户端只支持 inline 形式的 css 布局...

郁也风
今天
8
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部