Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1760158
  • 博文数量: 1493
  • 博客积分: 38
  • 博客等级: 民兵
  • 技术积分: 5834
  • 用 户 组: 普通用户
  • 注册时间: 2009-08-19 17:28
文章分类

全部博文(1493)

文章存档

2016年(11)

2015年(38)

2014年(137)

2013年(253)

2012年(1054)

2011年(1)

分类:

2012-11-14 14:40:05

1. 利用多核多线程进行程序优化

 

1.1 实验介绍

进程(process)和文件(files)是UNIX/Linux操作系统两个最基本的抽象。

进程是处于执行期的程序和它所包含的资源的总和,也就是说一个进程就是处于执行期的程序。一个线程(thread)就是运行在一个进程上下文中的一个逻辑流,不难看出,线程是进程中最基本的活动对象。

在传统的系统中,一个进程只包含一个线程。但在现代操作系统中,允许一个进程里面可以同时运行多个线程,这类程序就被称为多线程程序。所有的程序都有一个主线程(main thread),主线程是进程的控制流或执行线程。在多线程程序中,主线程可以创建一个或多个对等线程(peer thread),从这个时间点开始,这些线程就开始并发执行。主线程和对等线程的区别仅在于主线程总是进程中第一个运行的线程。从某种程度上看,线程可以看作是轻量级的进程(lightweight process)。

Linux操作系统中,内核调度的基本对象是线程,而不是进程,所以进程中的多个线程将由内核自动调度。

每个线程都拥有独立的线程上下文(thread context),线程IDThread IDTID),程序计数器(pc),线程栈(stack),一组寄存器(register)和条件码。其中,内核正是通过线程IDTID)来识别线程,进行线程调度的。

POSIX线程库定义了线程属性对象,它封装了线程的创建者可以访问和修改的线程属

性。线程属性主要包括如下属性:

1. 作用域(scope

2. 栈尺寸(stack size

3. 栈地址(stack address

4. 优先级(priority

5. 分离的状态(detached state

6. 调度策略和参数(scheduling policy and parameters

1.2 实验目标

程序功能:求从1一直到 APPLE_MAX_VALUE (100000000) 相加累计的和,并赋值给 apple  a  b ;求 orange 数据结构中的 a[i]+b[i ] 的和,循环 ORANGE_MAX_VALUE (1000000) 次。

说明:

1.     由于样例程序是从实际应用中抽象出来的模型,所以本文不会进行 test.a=test.b= test.b+sum 、中间变量(查找表)等类似的优化。

2.     以下所有程序片断均为部分代码,完整代码请参看本文最下面的附件。


1. 样例程序

#define ORANGE_MAX_VALUE      1000000

#define APPLE_MAX_VALUE       100000000

#define MSECOND               1000000

 

struct apple

{

     unsigned long long a;

unsigned long long b;

};

 

struct orange

{

            int a[ORANGE_MAX_VALUE];

            int b[ORANGE_MAX_VALUE];

           

};

 

int main (int argc, const char * argv[]) {

    // insert code here...

     struct apple test;

            struct orange test1;

           

            for(sum=0;sum

            {

                        test.a += sum;

                        test.b += sum;

            }

           

     sum=0;

            for(index=0;index

            {

                        sum += test1.a[index]+test1.b[index];

            }

 

     return 0;

}

 

      假设有一台酷睿2代双核机器,在此机器上对上述程序进行如下优化,您会如何选

择呢?

        Q1: 您认为样例程序还有优化的空间吗? 如果有,优化后的效率将会提升:

        A.  1%~30%              B.  30%~50%              C. 50%~90%              D.  90%以上         

 

        Q2: 如果将样例程序修改为两个线程,一个线程用于计算apple的和,另外一个线

程计算orange的和,您认为谁的效率会更高?

        A.  两线程              B.  单线程(样例程序)              C. 不确定

 

        Q3:  基于Q2,再将计算apple的线程拆成两个线程,一个线程用于计算apple a

(加锁访问),另外一个线程计算apple b的值(加锁访问),第三个线程计算orange的和,您认为谁的效率会更高?

        A.  两线程        B.  单线程(样例程序)        C. 三线程         D.  不确定

 

        Q4:  基于Q2,在双核CPU系统上,将计算apple的线程绑定到 CPU 0上运行,

将计算orange和的线程绑定到 CPU 1上运行,这种方法称为设臵CPU亲和力

CPU  Affinity ,也叫 CPU 绑定) 您认为谁的效率会更高?

        A.  两线程     B.  单线程(样例程序)    C. 两线程(CPU绑定)     D.  不确定

 

        Q5:  经过分析发现计算orange的和比较快,而计算apple的和比较慢。 基于Q3

将计算apple a的线程和计算orange和的线程绑定到CPU 0上运行,将计算apple b的线程绑定到 CPU 1上运行, 您认为谁的效率会更高?

        A.  三线程     B.  单线程(样例程序)    C. 三线程(CPU绑定)     D.  不确定

 

        Q6:  Q3中,将程序拆成多线程,需要加锁来访问apple ab的值,但由于他

们访问的是数据结构中的不同属性,也可以不加锁, 此时您认为谁的效率会更高?

        A.  加锁访问          B.  不加锁访问          C. 不确定

单线程原始程序平均耗时:1.049046s,最慢的不加锁三线程方案平均耗时:

2.217413s,最快的三线程(Cache128)平均耗时:0.826674s,效率提升约26%。当然,还可以进一步优化,让效率得到更高的提升。

从上图不难得出结论:采用多核多线程并行设计方案,能有效提高性能,但如果考虑

不全面,如忽略带宽、数据竞争及数据同步不当等因素,效率反而降低,程序执行越来越慢。

阅读(225) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~