• 多线程的那点儿事(之多核编程)


    【 声明:版权所有,欢迎转载,请勿用于商业用途。  联系信箱:feixiaoxing @163.com】

        多核编程并不是最近才兴起的新鲜事物。早在intel发布双核cpu之前,多核编程已经在业内存在了,只不过那时候是多处理器编程而已。为了实现多核编程,人们开发实现了几种多核编程的标准。open-mp就是其中的一种。对于open-mp还不太熟悉的朋友,可以参照维基百科的相关解释。


        open-mp的格式非常简单,原理也不难。它的基本原理就是创建多个线程,操作系统把这几个线程分到几个核上面同时执行,从而可以达到快速执行代码的目的。比如说,我们可以编写一个简单的例子。


        在编写open-mp程序之前,朋友们应该注意下面三点,

        (1) 使用vs2005或者以上的版本编写open-mp程序;

        (2) 编写程序的时候,选择【Property Pages】->【Configuration Properties】->【c/c++】->【language】->【OpenMp Support】,打开开关;       

        (3) 添加#include <omp.h> 声明。


        首先,我们编写简单的一个打印程序,看看结果。

    1. #include <omp.h>  
    2.   
    3. void print()  
    4. {  
    5.     int i;  
    6. #pragma omp parallel for  
    7.     for(i = 0; i < 100; i ++)  
    8.     {  
    9.         printf("%d ", i);  
    10.     }      
    11. }  
        上面这段代码好像也没有什么特别的地方,但是我们可以在printf设一个断点,看看函数调用堆栈,

    1. openmp.exe!print$omp$1()  Line 14   C++  
    2. vcompd.dll!_vcomp::ParallelRegion::HandlerThreadFunc()  + 0x19c bytes     
    3. vcompd.dll!_vcomp::ParallelRegion::HandlerThreadFunc()  + 0xe0 bytes      
    4. vcompd.dll!_InvokeThreadTeam@12()  + 0x98 bytes   
    5. vcompd.dll!__vcomp_fork()  + 0x1cd bytes      
    6. openmp.exe!print()  Line 11 + 0xe bytes C++  
    7. openmp.exe!wmain(int argc=1, wchar_t * * argv=0x003b5ba8)  Line 22  C++  
    8. openmp.exe!__tmainCRTStartup()  Line 583 + 0x19 bytes   C  
    9. openmp.exe!wmainCRTStartup()  Line 403  C  
    10. kernel32.dll!7c817077()       
    11. [Frames below may be incorrect and/or missing, no symbols loaded for kernel32.dll]  
        我们看可以看到函数堆栈和平时看到的一般函数调用确实不一样,但这确实也说明不了什么,不过没有关系,我们可以做一个简单的测试,

    1. #include "stdafx.h"  
    2. #include <windows.h>  
    3. #include <omp.h>  
    4.   
    5. #define NUMBER 1000000000  
    6.   
    7. int process(int start, int end)  
    8. {  
    9.     int total;  
    10.   
    11.     total = 0;  
    12.     while(start < end){  
    13.         total += start %2;  
    14.         start ++;  
    15.     }  
    16.   
    17.     return total;  
    18. }  
    19.   
    20. void test1()  
    21. {  
    22.     int i;  
    23.     int time;  
    24.     struct {  
    25.         int start;  
    26.         int end;  
    27.     }value[] = {  
    28.         {0 , NUMBER >> 1},  
    29.         {NUMBER >> 1, NUMBER}  
    30.     };  
    31.     int total[2] = {0};  
    32.     int result;  
    33.   
    34.     time = GetTickCount();  
    35.   
    36. #pragma omp parallel for  
    37.     for(i = 0; i < 2; i ++)  
    38.     {  
    39.         total[i] = process(value[i].start, value[i].end);  
    40.     }      
    41.       
    42.     result = total[0] + total[1];  
    43.     printf("%d ", GetTickCount() - time);  
    44. }  
    45.   
    46. void test2()  
    47. {  
    48.     int i;  
    49.     int value;  
    50.     int total;  
    51.   
    52.     total = 0;  
    53.     value = GetTickCount();  
    54.   
    55.     for(i = 0; i < NUMBER; i++)  
    56.     {  
    57.         total += i %2;  
    58.     }  
    59.     printf("%d ", GetTickCount()-value);  
    60. }  
    61.   
    62.   
    63. int _tmain(int argc, _TCHAR* argv[])  
    64. {  
    65.     test1();  
    66.     test2();  
    67.     return 0;  
    68. }  

        test1和test2完成的功能都是一样的,但是明显test1要比test2花费的时间要少很多,这明显就是多核编程的好处。所以要想实现多核编程最大程度上的并行运算,就必须把运
    算拆分成n个子运算,并且尽量减少使用锁。


    总结:
        (1) 这篇文章只是介绍性的博客,详细内容可以参考周伟明先生的博客;

        (2) 关于多核编程更具体的细节和方法,可以参考《多核计算与程序设计》这本书;

        (3) 编写多核编程需要的条件很简单,cpu支持多核、打开openmp开关、添加omp头文件,剩下的就是多多练习了;

        (4) 并行运算的时候少使用锁,否则效率会大打折扣。

  • 相关阅读:
    PHP对象
    MySQL多表更新
    使用not in的子查询
    MySQL比较运算符的子查询
    控制器调用函数
    MVC目录规范
    MVC流程
    mxnet安装
    离线安装Python包hickle,easydict
    深度学习基础
  • 原文地址:https://www.cnblogs.com/hzcya1995/p/13318822.html
Copyright © 2020-2023  润新知