C++简并行计算技术措施研究

   
这首稿子要写于咱这些非计算机专业的还要使写序、实现算法的丁,有的连多线程都无见面,所以这边虽说把未需要非常篇幅修改程序即使可省略实现之并行计算。

   
这边将并行计算分为2类,基于CPU的多线程处理、基于异构架构的并行计算(如GPU等)。基于CPU的第一出:OpenMP、TBB、PPL、Parallel、IPP等,基于异构的并行计算主要有OpenCL、CUDA、AMP等。以上自啊远非任何用到了,这里只介绍部分,以后用了再次补偿吧。

名解释
线程锁,是借助如果线程没有抢到线程锁,那么线程就会叫堵塞,线程所于的CPU会发生过程调度,选择任何进程执行。
并行计算(Parallel
Computing),是乘又以多算资源解决计算问题之进程,是增强计算机体系计算速度跟处理能力的等同种有效手段。

  • OpenMP

  • 使原则:语言
    C/C++、Fortran,编译器 Sun Studio、Intel Compiler、Microsoft Visual
    Studio、GCC(但不光限于) ,这里只介绍了对for循环的优化

  • 使用要:

    打开编译器OpenMP开关:如VS,点击工程的Properties,弹出菜单里,点击
    Configuration Properties->C/C++->Language->OpenMP
    Support,在下拉菜单里甄选Yes。

    应用头文件:#include
    <omp.h>

    加盟并行计算:在for循环前面加上#pragma
    omp parallel for

    线程锁:#pragma omp critical{…}
    一体化例程:

    #include <iostream>
    #include <omp.h>
    int main()
    {
        int sum = 0;
        int a[10] = {1,2,3,4,5,6,7,8,9,10};
        int coreNum = omp_get_num_procs();//获得处理器个数
        int* sumArray = new int[coreNum];//对应处理器个数,先生成一个数组
        for (int i=0;i<coreNum;i++)//将数组各元素初始化为0
            sumArray[i] = 0;
    #pragma omp parallel for
        for (int i=0;i<10;i++)
        {
            int k = omp_get_thread_num();//获得每个线程的ID
            sumArray[k] = sumArray[k]+a[i];
        }
        for (int i = 0;i<coreNum;i++)
            sum = sum + sumArray[i];
        std::cout<<"sum: "<<sum<<std::endl;
        return 0;
    }
  1. 注意:
    对for循环的优化,其真相是每个核分段处理,例如 for (int i=0;i<40;i++) 而CPU有4单核心,这CPU0
    处理i=0~9,CPU2处理1=10-19…以此类推,所以在每次循环有内外影响时许小心不要以并行处理。
  2. 延阅读:
    openMP的某些以更 – yangyangcv –
    博客园.html
    http://www.cnblogs.com/yangyangcv/archive/2012/03/23/2413335.html
    OpenMP创建线程中之锁及原子操作性能于
    http://blog.csdn.net/drzhouweiming/article/details/1689853

  3. Parallel

  4. 用标准:.NET
    Framework 4以上

  5. 以要:
    增补加命名空间:using System.Threading.Tasks
    动一下措施代替for、foreach:
    Parallel.For(int fromInclusive,int toExclusive,Action<int,
    ParallelLoopState> body)
    Parallel.ForEach<TSource>(IEnumerable<TSource>
    source,Action<TSource> body)
    整体例程:

    using System;
    using System.Threading.Tasks;
    
    public class Example
    {
       public static void Main()
       {
          ParallelLoopResult result = Parallel.For(0, 100, ctr => 
          { 
                Random rnd = new Random(ctr * 100000);
                Byte[] bytes = new Byte[100];
                rnd.NextBytes(bytes);
                int sum = 0;
                foreach(var byt in bytes)
                    sum += byt;
                Console.WriteLine("Iteration {0,2}: {1:N0}", ctr, sum);
          });
          Console.WriteLine("Result: {0}", result.IsCompleted ? "Completed Normally" : String.Format("Completed to {0}", result.LowestBreakIteration));
       }
    }
    
  6. 拉开阅读:
    MSDN
    https://msdn.microsoft.com/zh-cn/library/system.threading.tasks.parallel\_methods(v=vs.100).aspx.aspx)

  7. PPL

类似C#的Parallel,详见《遇见PPL:C++
的互相和异步》

  • AMP

 
为什么选在GPU上举行并行计算呢?现在之多核CPU一般都是对审或四审的,如果拿超线程技术考虑进去,可以把它当四单或八只逻辑核,但现的GPU动则就是那么些独审批,比如中端的 style=”font-size: small;”>NVIDIA GTX 560
SE style=”font-size: small;”>就有288个核,顶级的 style=”font-size: small;”>NVIDIA GTX
690 style=”font-size: small;”>更产生差不多上3072独审批,这些超多核(many-core)GPU非常适合大规模并行计算。
 
但是GPU的每个中心计算能力尚无CPU那么大,适合做海量数据的简要处理。

  1. 动用规范:语言C/C++,编译器VS2012和以上、C++11,运行环境DX11之上(Win7上述操作系统安装时显卡驱动都可支持,XP无缘)
  2. 使要:
    引用头文件:#include<amp.h> #include<amp_math.h>
    上加命名空间:using namespace concurrency::fast_math
    就支持就精度浮点数,而using namespace concurrency::precise_math
    则指向只精度浮点数和双精度浮点数均提供支撑。
    拿array数组对象封装到array_view对象中。
    使用parallel_for_each循环。
    完例程:

    #include <amp.h>
    #include <iostream>
    using namespace concurrency;
    
    const int size = 5;
    
    void CppAmpMethod() {
        int aCPP[] = {1, 2, 3, 4, 5};
        int bCPP[] = {6, 7, 8, 9, 10};
        int sumCPP[size];
    
        // Create C++ AMP objects.
        array_view<const int, 1> a(size, aCPP);
        array_view<const int, 1> b(size, bCPP);
        array_view<int, 1> sum(size, sumCPP);
        sum.discard_data();
    
        parallel_for_each( 
            // Define the compute domain, which is the set of threads that are created.
            sum.extent, 
            // Define the code to run on each thread on the accelerator.
            [=](index<1> idx) restrict(amp)
        {
            sum[idx] = a[idx] + b[idx];
        }
        );
    
        // Print the results. The expected output is "7, 9, 11, 13, 15".
        for (int i = 0; i < size; i++) {
            std::cout << sum[i] << "\n";
        }
    }
    
  3. 注意
    含 restrict(amp) 子句的函数具有以下限制:

  4. 函数只能调用具有 restrict(amp) 子句之函数。

  5. 函数必须可内联。

  6. 函数只能声明 int、unsigned int、float 和 double
    变量,以及才包含这些类别的切近及组织。 也同意利用
    bool,但如你当复合类型受到采用她,则它要是 4 字节对一起的。

  7. Lambda 函数无法透过引用捕获,并且无法捕获指针。

  8. 不过支持引用和纯粹间接指针作为片变量、函数参数和归路。

  9. 免允许用以下项:

    • 递归。

    • 使用
      volatile
      关键字声明的变量。

    • 虚函数。

    • 依靠于函数的指针。

    • 本着成员函数的指针。

    • 结构被之指针。

    • 对指针的指针。

    • goto 语句。

    • Labeled 语句。

    • try 、catch 或 throw 语句。

    • 全局变量。

    • 静态变量。 请C++改用 tile_static
      关键字。

    • dynamic_cast 强制转换。

    • typeid 运算符。

    • asm 声明。

    • Varargs。

恢宏阅读
入门:http://www.infoq.com/cn/articles/cpp_amp_computing_on_GPU
MSDN:https://msdn.microsoft.com/zh-cn/library/hh265136.aspx