zoukankan      html  css  js  c++  java
  • 并行编程2——多核体系架构

    1.1  多核处理器定义

    多内核处理器架构是指:芯片设计工程师在单个处理器中集成两个或多个 “执行内核(即计算引擎)”。多内核处理器可直接插入到单一处理器基座中。但是,操作系统会把它的每个执行内核作为独立的逻辑处理器,为其分配相应的执行资源。要利用多核处理器的运算能力,需要改写操作系统和编译器,广泛使用的vista, vin7 等都能支持多核体系架构。

    1.2  多核发展趋势

    首先思考一个问题: 为什么微处理器要从单核转向多核?

    答案是: 功耗问题限制了单核不断提高性能的发展途径.
    有几个简单的公式可以说明这个问题:

    1)    处理器性能 = 主频 * IPC , 主频是指每秒时钟周期数,比如1Ghz,是每秒10亿个时钟周期。IPC 是每个时钟周期可以执行的指令数。

    2)    处理器功耗 正比 电流*电压^2*主频, 而主频正比电压,所以

    处理器功耗 正比 主频^3 ,通过主频提升性能,要面临功耗以3次方的指数增长问题。所以主频发展到一定程度后,自然转到重点依靠提高ipc来提升性能,提升IPC可以通过提高指令的并行度实现,提高并行度,一是提高微处理器微架构的并行度,二是采用多核架构,(参考 : http://blogs.intel.com/china/2007/06/03/post_5/)前者已经发展了很多年,提升空间和投入产出比明显不如后者,所有多核处理器是未来的方向。

     下面两张图看出家庭版PC和手机核心数目也很快突破10个。目前最新的mac pro 已经配备12个核心

    图1 : 目前最新的mac pro 已经配备12个核心

    图2 三星也推出了8核手机处理器

    虽然商用多核(multicore)和众核(many-core)系统越来越普遍,成本也越来越低,游戏设备、手机等移动设备也具备越来越多的核心,并发和并行越来越成为必要的技术手段,但多核程序的发展依然没有跟上硬件的发展,很多游戏引擎和网络引擎都还是单线程的。原因就是第一章提到的多核编程的难度。

    1.3 一个多核处理器架构例子

    这是基于共享缓存的多核体系架构的一个例子,一共有10个核心,不需要深入了解,这张图唯一的目的就是给大家一个概念,现代的处理器架构已经比几十年前的冯诺依曼体系复杂多了(各种box),里边稍微值得关注的是Cbox ,Bbox ,这两个组件是缓存控制器,负责非常核心的功能:缓存一致性。缓存一致性会在后续文章描述。

    这张图是intel多核体系架构(双路)的缓存示意图,每个core拥有自己的L1和L2缓存,属于一个物理CPU的core共享L3缓存。不同cpu之间通过QPI交互L3数据。每个CPU有自己的内存控制器。对多核编程而言,缓存是非常重要的底层概念。

    1.4 Linux 线程核绑定

    这么多核具体到编程是如何使用的?

    在linux平台提供了核亲和性机制,进程和线程都可以通过设置亲和性绑定到不同的核心上。

    进程版本:

    #include <sched.h>

    void setProcessToCPU(int _cpuID)

    {

        cpu_set_t mask;

        cpu_set_t get;

     

        CPU_ZERO(&mask);

        CPU_SET(_cpuID, &mask);

     

        if (sched_setaffinity(0, sizeof(mask), &mask) < 0) {

            cout << "set process affinity failed " << endl;

        }

        CPU_ZERO(&get);

        if (sched_getaffinity(0, sizeof(get), &get) < 0) {

            cout << "get process affinity failed " << endl;

        }

    }

     

    线程版本:

    #include <pthread.h>

    #include <sched.h>

    void setThreadToCPU(int _cpuID)

    {

        cpu_set_t mask;

        cpu_set_t get;

     

        CPU_ZERO(&mask);

        CPU_SET(_cpuID, &mask);

     

        if (pthread_setaffinity_np(pthread_self(), sizeof(mask), &mask) < 0) {

            cout << "set thread affinity failed " << endl;

        }

        CPU_ZERO(&get);

        if (pthread_getaffinity_np(pthread_self(), sizeof(get), &get) < 0) {

            cout << "get thread affinity failed " << endl;

        }

    }

     

  • 相关阅读:
    SGX技术初探
    DH 密钥交换算法
    SSM整合框架实现ajax校验
    为什么要重写toString()方法和hashcode()方法
    java数组实现简单的DVD管理
    java冒泡排序
    windows下java环境变量配置
    Java实现视频网站的视频上传、视频转码、视频关键帧抽图, 及视频播放功能
    Eclipse SVN 冲突的 介绍 及 四种解决方式
    java中的重载(overload)和重写(override)区别
  • 原文地址:https://www.cnblogs.com/jiayy/p/3243842.html
Copyright © 2011-2022 走看看