精华内容
下载资源
问答
  • CELL处理器、Intel Core 2处理器的并行计算基本原理 Cell处理器并行编程基本技术:CELL处理器 pThread并行编程技术: Intel多核处理器、AMD多核处理器、SMP服务器 MPI并行编程技术:SMP多核服务器、CLUSTER、MPP...
  • 多核与异步并行

    千次阅读 2013-09-13 15:47:22
    多核与异步并行原文发表于《程序员》杂志2012年第9期,文字略有修改。我们在设计多线程程序时往往有很多性能指标,例如低延迟(latency),高吞吐量(throughput),高响应度(responsiveness)等。随着多核处理器上...

    多核与异步并行

    原文发表于《程序员》杂志2012年第9期,文字略有修改。

    我们在设计多线程程序时往往有很多性能指标,例如低延迟(latency),高吞吐量(throughput),高响应度(responsiveness)等。随着多核处理器上CPU核数的日益增加,如何高效地利用这些计算资源以满足这些设计目标变得越来越重要。这次向大家介绍的异步并行就是一种帮助实现低延迟、高吞吐量和高响应度的并行编程技术。

    让我们先来看这样一个例子。在下面的程序中,我们有一个do_something()的API,这个函数实现了将一个文件写入磁盘的功能,所以改函数比较耗时。在调用这个函数时,最简单的用法是对该函数进行同步调用,即下面程序中caller1()所采用的方式。这种写法带来的问题是,caller1需要阻塞等待do_something()的完成,期间CPU不能做任何其他的计算,从而导致CPU资源的空闲。与此相反,程序中的caller2就采用了异步调用do_something()的方式。这样,caller2在将异步调用do_something的命令发送给worker线程之后,就可以立刻返回并开始执行other_work(),不仅能将other_work()提前完成,更提高了CPU利用率。

    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    12
    13
    14
    15
    int do_something(doc)
    {
        return write_document(doc); // 耗时的I/O写操作
    }
     
    void caller1(doc) {
       result = do_something(doc); //同步调用do_something()
       other_work(); //这个操作需要等待do_something()的完成
       more_other_work();
    }
    void caller2() {
       worker.send(do_something_msg());//异步调用do_something()
       other_work(); //这个操作不需要等待do_something()的完成,因此提高了CPU的利用率
       more_other_work();
    }

    在现代计算机体系结构中,I/O设备的速度远远比不上CPU,我们在做计算时一个基本的设计原则就是在CPU等待I/O请求的同时,用足够多的计算任务将CPU跑满,从而掩盖掉I/O请求造成的延迟。在单核时代,我们使用Multiplexing的方式将I/O任务与计算任务重叠在一起进而提高程序性能,即一个进程如果进入I/O等待,操作系统会将该进程放入等待队列,并调度执行另一个进程的计算任务;多核时代来临之后,CPU上的计算资源变得越来越多,通过使用异步并行技术充分利用CPU的计算资源,提升应用程序的延迟性、吞吐量、响应度也变得越来越普遍。下面让我们通过几个典型应用来对异步并行做更多的介绍。

    GUI线程的异步并行设计

    GUI线程是采用异步并行设计来提高响应度的一个经典例子。一个GUI程序的典型结构是使用一个循环来处理诸如用户点击了某个按钮、系统产生了一个中断等事件。许多GUI系统还提供了诸如优先级队列等数据结构以保证优先级高的事件能得到及时的相应。下例是一个典型的GUI系统伪代码:

    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    while( message = queue.receive() ) {
      if( it is a "保存文件" request ) {
        save_document(); // 这是一个会产生阻塞的同步调用
      }
      else if( it's a "打印文档" request ) {
        print_document(); // 这是一个会产生阻塞的同步调用
      }
    else
      ...
    }

    这个程序有一个非常常见的性能bug:它对save_document()和print_document()这两个非常耗时的操作采用了同步调用的方式,这与GUI线程应该具备及时响应的设计初衷产生了直接矛盾。GUI线程的设计目标不仅仅是对相应的事件作出正确的响应,更重要的是这些响应必须非常及时。按照上面这个程序的逻辑,很可能会出现如下情况:用户在点击“保存文件”按钮之后,程序需要花费几秒钟才能完成save_document()调用,因此该程序在这几秒钟时间内都不能再对其他任何事件作出响应;而这时如果用户还想要调整窗口大小,这个操作在几秒钟之内都得不到响应,从而破坏用户体验。

    一般来说,需要拥有高响应度的线程不应该直接执行可能带来延迟或阻塞的操作。可能带来延迟或阻塞的操作不仅仅包括保存文件、打印文件,还包括请求互斥锁、等待其他线程某个操作的完成等。

    我们有三种方式来将耗时的操作从需要保持高响应度的线程中转移出去。下面让我们继续用GUI系统的例子来对这三种方法一一进行介绍,以分析它们各自适用的场景。

    方式一:一个专用的工作线程

    第一种将耗时操作从GUI线程中转移出去的方式是,使用一个专门的工作线程来异步地处理GUI线程发送的耗时操作请求。如下图所示,GUI线程依次将打印文档(PrintDocument)和保存文档(SaveDocument)两个异步请求发送给工作线程之后就立刻返回,从而继续对用户的其他请求做出及时的相应(例如调整窗口大小、编辑文档等);与此同时,工作线程依次对打印文档和保持文档进行顺序处理,并在并在该异步请求完成到某一进度时(或者该异步请求完成时)向GUI线程发送相应的通知信号。

    图1. 使用专门的工作线程来处理GUI线程的异步请求

    图1. 使用专门的工作线程来处理GUI线程的异步请求

    让我们来看看这种处理方式的代码会长成什么样子:

    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    // 第一种方式:使用一个专门的工作线程来处理GUI线程的异步请求
    // GUI线程:
    while( message = queue.receive() ) {
       if( it's a "保存文档" request ) {
          worker.send( new save_msg() ); // 发送异步请求
       }
       else if( it's a "保存文档" completion notification ) {
         display(“保存文档成功!”); // 接到异步请求的进度通知
       }
       else if( it's a "打印文档" request ) {
          worker.send( new print_msg() ); //发送异步请求
       }
       else if( it's a "打印文档" progress notification ) {
          if( percent < 100 ) // 接到异步请求的进度通知
             display_print_progress( percent );
          else
             display(“打印完毕!”);
       }
       else
       ...
    }
     
    // 工作线程:处理来自GUI线程的异步请求
    while( message = workqueue.receive() ) {
       if( it's a "保存文档" request )
          save_document(); // 保存文档并在结束后向GUI线程发送通知
       else if( it's a "打印文档 " request )
          print_document(); // 打印文档并向GUI线程发送进度通知
       else
       ...
    }

    方式二:每一个异步请求分配一个工作线程

    在第一种方法的基础之上,我们可以做一些相应的扩展:对每一个GUi线程的异步请求都分配一个专门的工作线程,而不是只用一个工作线程去处理所有异步请求。这个方式的好处很明显,异步请求被多个线程分别并行处理,因此提升了处理速度。值得注意的是,我们需要及时对这些工作线程进行垃圾回收操作,否则大量线程会造成内存资源的紧张。

    图2. 为每个GUI线程的异步请求分配一个工作线程

    图2. 为每个GUI线程的异步请求分配一个工作线程

    这种模式的代码如下所示。因为对每个异步请求我们都启动一个新的线程,我们可以充分地利用多核的计算资源,更快地完成相应的任务。

    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    12
    13
    14
    15
    // 方式二:每一个异步请求分配一个线程
    while( message = queue.receive() ) {
       if( it's a "保存文档" request ) {
          ...  new Thread( [] { save_dcument(); } ); // 启动新线程对异步请求进行处理
       }
       else if( it's a "打印文档" request ) {
          new Thread( [] { print_document(); } );/ // 启动新线程对异步请求进行处理
       }
       else if( it's a "保存文档" notification ) { ... }
                                          // 同方式一
       else if( it's a "打印文档" progress notification ) { ... }
                                          // 同方式一
       else
          ...
    }

    方式三:使用线程池来处理异步请求

    第三种方式更进了一步:我们可以根据多核硬件资源的多少来启动一个专门的线程池,用线程池来完成GUI线程的异步请求。这种方式的好处在于,我们可以在充分利用多核的硬件资源,以及并行地对异步请求进行高效处理间取得一个很好的平衡。该方式的工作示意图如下所示:

    图3. 使用线程池来处理GUI线程的异步请求

    图3. 使用线程池来处理GUI线程的异步请求

    让我们来看一下这种方式的伪代码。需要注意的是,线程池的具体实现每个语言各有不同,因此下面的代码只供大家参考之用。

    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    12
    13
    14
    15
    // 方式三:使用线程池来处理异步请求
    while( message = queue.receive() ) {
    if( it's a "保存文档" request ) {
    pool.run( [] { save_document(); } ); // 线程池的异步调用
    }
    else if( it's a "打印文档" request ) {
    pool.run( [] { print_document(); } ); //线程池的异步调用
    }
    else if( it's a "保存文档" notification ) { ... }
    // 同前
    else if( it's a "打印文档" progress notification ) {  ... }
    // 同前
    else
    ...
    }

    Grand Central Dispatch的异步并行

    Grand Central Dispatch(GCD)是苹果于Mac OS X 10.6和iOS4中发布的一项并行编程技术。对使用GCD的程序员来说,只需要将需要被处理的任务块丢到一个全局的任务队列中去就可以了,这个任务队列中的任务会由操作系统自动地分配和调度多个线程来进行并行处理。将需要被处理的任务块插入到任务队列中去有两种方式:同步插入和异步插入。

    让我们来看看一个使用GCD异步并行的实例。在下面的程序中,analyzeDocument函数需要完成的功能是对这个文档的字数和段落数进行相关统计。在分析一个很小的文档时,这个函数可能非常快就能执行完毕,因此在主线程中同步调用这个函数也不会有很大的性能问题。但是,如果这个文件非常的大,这个函数可能变得非常耗时,而如果仍然在主线程中同步调用该方法,就可能带来很大的性能延迟,从而影响用户体验。

    01
    02
    03
    04
    05
    06
    07
    // 不使用GCD的版本
    - (IBAction)analyzeDocument:(NSButton *)sender {
        NSDictionary *stats = [myDoc analyze];
        [myModel setDict:stats];
        [myStatsView setNeedsDisplay:YES];
        [stats release];
    }

    使用GCD的异步并行机制来优化这个函数非常简单。如下所示,我们只需要在原来的代码基础上,先通过dispatch_get_global_queue来获取全局队列的引用,然后再将任务块通过dispatch_async方法插入该队列即可。任务块的执行会交由操作系统去处理,并在该任务块完成时通知主线程。一般来讲,异步插入的方式拥有更高的性能,因为在插入任务之后dispatch_async可以直接返回,不需要进行额外等待。

    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    //使用GCD异步并行的版本
    - (IBAction)analyzeDocument:(NSButton *)sender
    {
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul);
    dispatch_async(queue, ^{
             NSDictionary *stats = [myDoc analyze];
             [myModel setDict:stats];
             [myStatsView setNeedsDisplay:YES];
             [stats release];
         });
    }

    总结

    本文对多核编程时常用的异步并行技术做了相关介绍。通过使用异步并行技术,我们可以将比较耗时的操作交给其他线程去处理,主线程因此可以去处理其他有意义的计算任务(例如相应用户的其他请求,完成其他计算任务等),从而有效提高系统的延迟性、吞吐率和响应性。

    展开全文
  • 并行程序设计 目前并行程序设计的状况是:①并行软件的发展落后于并行硬件;②和串行系统的应用软件相比,现今...②串行程序设计仅有一个普遍被接受的冯*诺依曼模型,而并行计算模型虽有好多,但没有一个被共同认可;

    并行程序设计

    目前并行程序设计的状况是:①并行软件的发展落后于并行硬件;②和串行系统的应用软件相比,现今的并行系统应用软件甚少且不成熟;③并行软件的缺乏是发展并行计算的主要障碍;④而且这种状态仍在继续.
    其原因是:①并行程序设计不但包含了串行程序设计,而且还包含了更多的富有挑战性的问题;②串行程序设计仅有一个普遍被接受的冯*诺依曼模型,而并行计算模型虽有好多,但没有一个被共同认可;③并行程序设计对环境工具的要求远比串行程序设计先进得多;④串行程序设计比较适合于自然习惯,且人们在过去积累了大量的编程知识和宝贵的软件财富.
    并行程序设计:对于所希望的应用,很多并行代码似乎不存在的;即使有,也常不能用于用户的并行机上.因为并行代码原来都是为不同的并行结构写的.
    它的问题是:至今并行算法范例不能被很好地理解和广泛地接受;并行程序设计是建立在不同的计算模型上的,而它们没有能像冯*诺依曼模型那样被普遍的接受和认可.绝大部分被使用的并行程序设计语言都是Fortran和C的推广,他们都不能够充分地表达不同并行结构的特点,既不成熟也不通用.并行程序设计工具依赖于具体的并行结构和计算机代的更迭,既不通用也不稳定,在某个并行平台上开发的并行程序很难移植到别的或将来的并行机上.
    目前并行编程类型逐渐汇聚于两类:用于PVP,SMP和DSW的共享变量的单地址空间模型和用于MPP和机群消息传递的多地址空间模型.
    并行编程模型逐渐汇聚于三类标准模型:数据并行(如:HPF),消息传递(如:MPI和PVM),和共享变量(如OpenMp).
    现在人们希望高性能的并行机应是 具有单一系统映像的巨大的工作站,使得很多用户都能利用增强处理能力和储存容量来运行多个串行作业,这就是所谓的串行程序并行系统SPPS.
    当我们在实际的并行机上设计并行程序时,绝大部分均是采用扩展Fortran和C语言的办法,目前有三种扩展的办法:一是库函数法:除了串行语言所包含的库函数外,一组新的支持并行性和交互操作的库函数(如MPI消息传递库和POSIXPthreads多线程库)引入到并行程序设计中。二是新语言结构法:采用某些新的语言结构来帮助并行程序设计以支持并行性和交互操作(如Fortran 90 中的聚集数组操作);  三是编译制导法:程序设计语言保持不变,但是将
    称之为编译制导的格式注释引入到并行程序中.

    并发是用来描述并行执行的方式(看上去一起发生的事件,例如目前操作系统的多任务调度程序,看上去桌面上有许多程序在同时运行.),并发是形容词.

    并行是指通过并发将一个操作分解成一组粒度更细的工作单元,并且这些工作单元可以在不同的处理器内核上运行.并行是动词,指必须有两个以上的事件发生.

    工作单元,以粒度可分为最小到单一CPU指令,大到函数或系统任务.

    并行有数据并行性与任务并行性

    数据并行性指对许多数据执行相同的并行操作,比如对一组数的每个数进行加法操作.

    任务并行性指对相同的一组数据执行不同的并行操作,比如一个执行加法操作,而另一个执行乘法操作.

    优秀的多核微处理器:AMD Multicore Opteron、Intel Core2 Duo

    并行编程的麻烦

    内存一致模型简称内存模型

    缓存一致性(cache coherency) 将缓存与主内存数据进行同步

    内存一致性模型(memory consistency model)

    CPU可以对内存的读取或写入操作重新排序(乱序执行Out of Order),而导致内存一致性的产生.就是指CPU中实际内存访问操作与程序代码中内存访问操作的不一致性程度.

    CPU的硬件架构决定了内存模型的强度,强度越高写代码就会更容易.

    x86/64架构的CPU有较强的内存一致性模型,而安腾系列处理器Itanium(IA-64)是较弱的模型.它为了提高性能(不必根踪缓存行的状态)不会主动刷新缓存,而是提供指令操作缓存刷新到主内存.

    还有一些软件实现的内存模型,比如java虚拟机和.NET CLR,它们都是比较强的内存模型,而且不考虑具体的硬件实现.

    解决办法:内存栅栏(memory fence)

    内存栅栏可以阻止目标架构对指令进行重排.利用语言平台的特性或原子方法可以实现内存栅栏,比如.net中的Interlocked类方法,c++中的volatile变量.

    附录一些并行库:

    Single Unix Specification的POSIX线程库.

    Intel的TBB线程库.

    Standard Template Adaptive Parallel Library,STAPL:标准模板适配并行库.

    最后并行编程库必须得到操作系统的支持,如果系统没有相应功能api,上面那些并行库也就一无是处了.  


    扩展阅读“
    http://www.doc88.com/p-715689960200.html
    展开全文
  • 1、锁竞争: 单核中,如果单个线程取得所,则获取CPU运行时间,其他等待获取锁的线程被阻塞。... 其他计算 并行进行)提高用户的操作性能! 多核中,分别出多个线程,不再限于将用户界面操作和其他计算...

    https://blog.csdn.net/liu857279611/article/details/71967601

     

    1、锁竞争:

    单核中,如果单个线程取得所,则获取CPU运行时间,其他等待获取锁的线程被阻塞。使用了锁,影响的只是枷锁和解锁的耗时,CPU始终运行。

     

    多核中,若2个(更多)线程使用同一把锁,则会导致CPU饥饿。实际还是串行化执行!

     

    2、线程分解和执行的区别:

    对单核CPU,对客户端软件,采用多线程,主要是 创建多线程将一些计算放在后台执行,而不影响用户交互操作。(用户界面 & 其他计算 并行进行)提高用户的操作性能!

     

    多核中,分别出多个线程,不再限于将用户界面操作和其他计算分离。分解多个线程使为了让计算分配到各CPU上执行。执行线程数量与CPU核数有关!如果线程数小于核数,某些CPU肯定处于空闲状态。

     

    3、CPU核负载平衡:

    单核中不考虑 负载平衡,各个线程计算量相差很大,也不会影响程序总计算时间。

    多核中,必须考虑将各个线程计算量均衡到各CPU

     

    4、任务调度策略区别:

    单核中,任务调度主要考虑分时,某些任务的优先执行!常用:时间片轮转,优先级抢占!

     

    多核中,任务调度比单核有新的需求。要考虑 不同任务的耗时,和计算均衡!不能采用简单的时间片轮转和优先级抢占。而总的调用操作系统不能掌握。需要程序员实现!

     

    5、CPU cache存取:

    CPU读取Cache时,以行为单位读取。如果2个硬件线程的两块不同内存位于同一Cache行。当2个硬件线程同时对各自的内存进行写操作,导致2个线程同时写一个cache行。冲突!!【 伪内存问题】

     

    单核机,不存在 伪内存问题

    多核机,存在伪内存问题!想办法,使不同的内存块映射到不同Cache行

     

    6、任务优先级抢先的区别:

    单核CPU中,优先级抢占很常见的任务调度策略。

    多核CPU中,多个核可导致,低优先级和高优先级的任务同时运行。需要进一步改进 优先级调度策略。

     

    7、串行计算与并行计算、分布式计算的区别

    单核多线程编程中,都是串行算法。用不到并行计算,更用不到分布式计算

    多核编程中,多采用 并行计算 和 分布式计算

     

    并行计算=并行设计模式+并行算法

    分布式计算复杂度 > 并行计算的复杂度 > 串行计算复杂度

     

    并行计算:只考虑计算并行地执行,不考虑线程间的竞争导致CPU饥饿

    分布式计算:相比并行计算,能更好解决CPU饥饿,使计算均衡地分配任务到各内核

     

    https://www.baidu.com/link?url=wnky8AaMNfYeJ03YonzOadkZyVyh7OdeLm4EWviN4o6JUf9zRaqP_WYIhVVi2ds6Fa7JBZDACAC0k-8Jb6DnjIqy7NrZbkJLX6jooNbDFpC&wd=&eqid=a381695800065586000000065f6ff4e9

    https://blog.csdn.net/liu857279611/article/details/71967601

     

    展开全文
  • 浅谈多核CPU、多线程与并行计算 xiaofei08592017-05-09 17:07:113646收藏 展开 0.前言 笔者用过MPI和C#线程池,参加过比赛,有所感受,将近一年来,对多线程编程兴趣一直不减,一直有所关注,决定写篇文章,...

    浅谈多核CPU、多线程与并行计算

    xiaofei0859 2017-05-09 17:07:11  3646  收藏

    展开

    0.前言

    笔者用过MPI和C#线程池,参加过比赛,有所感受,将近一年来,对多线程编程兴趣一直不减,一直有所关注,决定写篇文章,算是对知识的总结吧。有说的不对的地方,欢迎各位大哥们指正:)

    1.CPU发展趋势

    核心数目依旧会越来越多,依据摩尔定律,由于单个核心性能提升有着严重的瓶颈问题,普通的桌面PC有望在2017年末2018年初达到24核心(或者16核32线程),我们如何来面对这突如其来的核心数目的增加?编程也要与时俱进。笔者斗胆预测,CPU各个核心之间的片内总线将会采用4路组相连:),因为全相连太过复杂,单总线又不够给力。而且应该是非对称多核处理器,可能其中会混杂几个DSP处理器或流处理器。

     

    2.多线程与并行计算的区别

    (1)多线程的作用不只是用作并行计算,他还有很多很有益的作用。

    还在单核时代,多线程就有很广泛的应用,这时候多线程大多用于降低阻塞(意思是类似于

    while(1)

    {

    if(flag==1)

    break;

    sleep(1);

    }

    这样的代码)带来的CPU资源闲置,注意这里没有浪费CPU资源,去掉sleep(1)就是纯浪费了。

    阻塞在什么时候发生呢?一般是等待IO操作(磁盘,数据库,网络等等)。此时如果单线程,CPU会干转不干实事(与本程序无关的事情都算不干实事,因为执行其他程序对我来说没意义),效率低下(针对这个程序而言),例如一个IO操作要耗时10毫秒,CPU就会被阻塞接近10毫秒,这是何等的浪费啊!要知道CPU是数着纳秒过日子的。

    所以这种耗时的IO操作就用一个线程Thread去代为执行,创建这个线程的函数(代码)部分不会被IO操作阻塞,继续干这个程序中其他的事情,而不是干等待(或者去执行其他程序)。

    同样在这个单核时代,多线程的这个消除阻塞的作用还可以叫做“并发”,这和并行是有着本质的不同的。并发是“伪并行”,看似并行,而实际上还是一个CPU在执行一切事物,只是切换的太快,我们没法察觉罢了。例如基于UI的程序(俗话说就是图形界面),如果你点一个按钮触发的事件需要执行10秒钟,那么这个程序就会假死,因为程序在忙着执行,没空搭理用户的其他操作;而如果你把这个按钮触发的函数赋给一个线程,然后启动线程去执行,那么程序就不会假死,继续相应用户的其他操作。但是,随之而来的就是线程的互斥和同步、死锁等问题,详细见有关文献。

    现在是多核时代了,这种线程的互斥和同步问题是更加严峻的,单核时代大都算并发,多核时代真的就大为不同,为什么呢?具体细节请参考有关文献。我这里简单解释一下,以前volatile型变量的使用可以解决大部分问题,例如多个线程共同访问一个Flag标志位,如果是单核并发,基本不会出问题(P.S.在什么情况下会出问题呢?Flag有多个,或者是一个数组,这时候只能通过逻辑手段搞定这个问题了,多来几次空转无所谓,别出致命问题就行),因为CPU只有一个,同时访问这个标志位的只能有一个线程,而多核情况下就不太一样了,所以仅仅volatile不太能解决问题,这就要用到具体语言,具体环境中的“信号量”了,Mutex,Monitor,Lock等等,这些类都操作了硬件上的“关中断”,达到“原语”效果,对临界区的访问不被打断的效果,具体就不解释了,读者可以看看《现代操作系统》。

    (2)并行计算还可以通过其他手段来获得,而多线程只是其中之一。

    其他手段包括:多进程(这又包括共享存储区的和分布式多机,以及混合式的),指令级并行。

    ILP(指令级并行),x86架构里叫SMT(同时多线程),在MIPS架构里与之对应的是super scalar(超标量)和乱序执行,二者有区别,但共同点都是可以达到指令级并行,这是用户没法控制的,不属于编程范围,只能做些有限的优化,而这有限的优化可能只属于编译器管辖的范畴,用户能做的甚少。

    (3)典型的适于并行计算的语言

    Erlang和MPI:这两个前者是语言,后者是C++和Fortran的扩展库,效果是一样的,利用多进程实现并行计算,Erlang是共享存储区的,MPI是混合型的。

    C#.NET4.0:新版本4.0可以用少量代码实现并行For循环,之前版本需要用很繁琐的代码才能实现同样功能。这是利用了多线程实现并行计算。Java和C#3.5都有线程池(ThreadPool),也是不错的很好用的多线程管理类,可以方便高效的使用多线程。

    CUDA,还是个初生牛犊,有很大的发展潜力,只不过就目前其应用领域很有限。其目前只能使用C语言,而且还不是C99,比较低级,不能使用函数指针。个人感觉这由于硬件上天生的局限性(平均每个核心可用内存小,与系统内存通讯时间长),只适用于做科学计算,静态图像处理,视频编码解码,其他领域,还不如高端CPU。等以后GPU有操作系统了,能充分调度GPU资源了,GPU就可以当大神了。游戏中的物理加速,实际上多核CPU也能很好的做到。

    其他语言。。。恩。。留作将来讨论。

     

    3.线程越多越好吗?什么时候才有必要用多线程?

    线程必然不是越多越好,线程切换也是要开销的,当你增加一个线程的时候,增加的额外开销要小于该线程能够消除的阻塞时间,这才叫物有所值。

    Linux自从2.6内核开始,就会把不同的线程交给不同的核心去处理。Windows也从NT.4.0开始支持这一特性。

    什么时候该使用多线程呢?这要分四种情况讨论:

    a.多核CPU——计算密集型任务。此时要尽量使用多线程,可以提高任务执行效率,例如加密解密,数据压缩解压缩(视频、音频、普通数据),否则只能使一个核心满载,而其他核心闲置。

    b.单核CPU——计算密集型任务。此时的任务已经把CPU资源100%消耗了,就没必要也不可能使用多线程来提高计算效率了;相反,如果要做人机交互,最好还是要用多线程,避免用户没法对计算机进行操作。

    c.单核CPU——IO密集型任务,使用多线程还是为了人机交互方便,

    d.多核CPU——IO密集型任务,这就更不用说了,跟单核时候原因一样。

    4.程序员需要掌握的技巧/技术

    (1)减少串行化的代码用以提高效率。这是废话。

    (2)单一的共享数据分布化:把一个数据复制很多份,让不同线程可以同时访问。

    (3)负载均衡,分为静态的和动态的两种。具体的参见有关文献。

    展开全文
  • 多线程与多核编程.pdf

    热门讨论 2011-09-09 09:30:37
    多任务的并发执行会用到多线程 (multithreading),而CPU 的多核 (mult-core)化又将 原来只在巨型机中才使用的并行计算 (parallel computing)带入普通PC 应用的多核程序设 计 (multi-core programming)中。
  • 最近研究并行计算,将搜到的并行方法记录一下,以便学习查找  随着多核时代的到来流行,传统的单线程串行程序的编程模式必将改变,取而代之的将是并行编程。目前已经有五种主要并行编程模型,下面将对此五种...
  • 混合并行编程技术将节点间的分布式存储节点内的共享存储进行了融合。针对多核SMP集群体系结构的特点,进一步研究了适用于多核SMP集群的层次化混合并行编程模型MPI/OpenMP,以及多核SMP节点间和节点内多级并行的...
  • 本节书摘来自华章出版社《多核与GPU编程:工具、方法及实践》一书中的第1章,第1.2节, 作 者 Multicore and GPU Programming: An Integrated Approach[阿联酋]杰拉西莫斯·巴拉斯(Gerassimos Barlas) 著,...
  • 过去半个世纪中,摩尔定律一直指导半导体科技产业的发展。英特尔一直遵循摩尔定律,一般每隔两年左右就会发布新成果。不过现在有一些专家指出计算机已经达到摩尔定律的物理极限。科技的不断进步,晶体管制作不断...
  • 本节书摘来自华章出版社《多核与GPU编程:工具、方法及实践》一书中的第2章,第2.1节, 作 者 Multicore and GPU Programming: An Integrated Approach[阿联酋]杰拉西莫斯·巴拉斯(Gerassimos Barlas) 著,...
  • 笔者用过MPI和C#线程池,参加过比赛,有所感受,将近一年来,对多线程编程兴趣一直不减,一直有所关注,决定写篇文章,算是对知识的总结吧。有说的不对的地方,欢迎各位大哥们指正:) 1.CPU发展趋势 核心数目.....
  • 第24章 并发和多核编程 第一部分并发编程 当我们写这本书的时候,CPU架构正在以比过去几十年间更快的速度变化。 并发和并行的定义 并发程序需要同时执行多个不相关任务。考虑游戏服务器的例子:它通常是由...
  • 本节书摘来自华章出版社《多核与GPU编程:工具、方法及实践》一书中的第1章,第1.5节, 作 者 Multicore and GPU Programming: An Integrated Approach[阿联酋]杰拉西莫斯·巴拉斯(Gerassimos Barlas) 著,...
  • 多核并行开发

    2009-10-18 19:48:00
    在科学工程计算、大型数据库、监控中心等领域,性能需求高于编程代价,早在单核 时代,就已经广泛采用单主机上的多CPU,乃至多主机集群的结构,自然也很早就开始使 用并行程序——有单进程多线程的并行,有单机多...
  • 目 录[第1章 概述 1.1 多核计算机时代 ](https://yq.aliyun.com/articles/90097)1.2 并行计算机的分类 [1.3 现代计算机概览 1.3.1 Cell BE处理器 1.3.2 NVIDIA Kepler 1.3.3 AMD APU 1.3.4 从多核到众核:...
  • 为执行并行计算,计算资源应包括一台配有多处理机(并行处理)的计算机、一个网络相连的计算机专有编号,或者两者结合使用。并行计算的主要目的是快速解决大型且复杂的计算问题。此外还包括:利用非本地资源,节约...
  • :并发编程与多核时代的王者       孟岩谈Erlang:并行计算和云计算 赵东炜:Erlang助你迎接多核时代的挑战     “Erlang 让我有醍醐灌顶之感,它促使我开始以完全不同的方式思考问题。Amstrong 能够...
  • 利用多核并行技术,使用PthreadsOpenMP并行编程环境在单机双核平台上开发小波包并行算法。通过分析串行算法潜在并行性,基于Pthreads将小波包分解数据分组并分配给不同的线程,由线程并行处理;根据小波包重构对象...

空空如也

空空如也

1 2 3 4 5 ... 10
收藏数 185
精华内容 74
关键字:

多核编程与并行计算