簡單並行計算技術方法研究

来源:http://www.cnblogs.com/chihirosan/archive/2016/02/29/5226760.html
-Advertisement-
Play Games

這篇文章主要寫給我們這些非電腦專業的又要寫程式、實現演算法的人,有的連多線程都不會,所以這裡就說些不需要大篇幅修改程式就可以簡單實現的並行計算。 這邊把並行計算分為2類,基於CPU的多線程處理、基於異構架構的並行計算(如GPU等)。基於CPU的主要有:OpenMP、TBB、PPL、Parallel、


    這篇文章主要寫給我們這些非電腦專業的又要寫程式、實現演算法的人,有的連多線程都不會,所以這裡就說些不需要大篇幅修改程式就可以簡單實現的並行計算。

    這邊把並行計算分為2類,基於CPU的多線程處理、基於異構架構的並行計算(如GPU等)。基於CPU的主要有:OpenMP、TBB、PPL、Parallel、IPP等,基於異構的並行計算主要有OpenCL、CUDA、AMP等。以上我也沒有全部使用過,這裡只介紹部分,以後用了再補充吧。

名稱解釋
線程鎖,是指如果線程沒有搶到線程鎖,那麼線程就會被阻塞,線程所在的CPU會發生進程調度,選擇其他進程執行。
並行計算(Parallel Computing),是指同時使用多種計算資源解決計算問題的過程,是提高電腦系統計算速度和處理能力的一種有效手段。

  • OpenMP
  1. 使用條件:語言 C/C++、Fortran,編譯器 Sun Studio、Intel Compiler、Microsoft Visual Studio、GCC(但不僅限於) ,這裡只介紹了對for迴圈的優化
  2. 使用要點:

    開啟編譯器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;
    }
  3. 註意:
    對於for迴圈的優化,其本質是每個核分段處理,例如
    for (int i=0;i<40;i++) 而CPU有4個核心,這CPU0 處理i=0~9,CPU2處理1=10-19…以此類推,所以在每次迴圈有前後影響時應註意不要使用並行處理。
  4. 延伸閱讀:
    openMP的一點使用經驗 - yangyangcv - 博客園.html
    http://www.cnblogs.com/yangyangcv/archive/2012/03/23/2413335.html
    OpenMP創建線程中的鎖及原子操作性能比較
    http://blog.csdn.net/drzhouweiming/article/details/1689853
  • Parallel
  1. 使用條件:.NET Framework 4以上
  2. 使用要點:
    添加命名空間: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));
       }
    }
  3. 延伸閱讀:
    MSDN
    https://msdn.microsoft.com/zh-cn/library/system.threading.tasks.parallel_methods(v=vs.100).aspx
  • PPL

類似C#的Parallel,詳見《遇見PPL:C++ 的並行和非同步》

  • AMP

  為什麼選擇在GPU上做並行計算呢?現在的多核CPU一般都是雙核或四核的,如果把超線程技術考慮進來,可以把它們看作四個或八個邏輯核,但現在的GPU動則就上百個核,比如中端的NVIDIA GTX 560 SE就有288個核,頂級的NVIDIA GTX 690更有多達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) 子句的函數具有以下限制:
    • 函數只能調用具有 restrict(amp) 子句的函數。

    • 函數必須可內聯。

    • 函數只能聲明 int、unsigned int、float 和 double 變數,以及只包含這些類型的類和結構。 也允許使用 bool,但如果您在複合類型中使用它,則它必須是 4 位元組對齊的。

    • Lambda 函數無法通過引用捕獲,並且無法捕獲指針。

    • 僅支持引用和單一間接指針作為局部變數、函數參數和返回類型。

    • 不允許使用以下項:

      • 遞歸。

      • 使用 volatile 關鍵字聲明的變數。

      • 虛函數。

      • 指向函數的指針。

      • 指向成員函數的指針。

      • 結構中的指針。

      • 指向指針的指針。

      • goto 語句。

      • Labeled 語句。

      • try 、catch 或 throw 語句。

      • 全局變數。

      • 靜態變數。 請改用 tile_static 關鍵字

      • dynamic_cast 強制轉換。

      • typeid 運算符。

      • asm 聲明。

      • Varargs。

  4. 擴展閱讀
    入門:http://www.infoq.com/cn/articles/cpp_amp_computing_on_GPU
    MSDN:https://msdn.microsoft.com/zh-cn/library/hh265136.aspx

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 示例闡述C++中的文件操作
  • 1.getgamedesc.sh 功能:插入gamedesc.txt文本中的,以“,”分割的第1列數據gid和第6列數據desc,到線網mysql資料庫中(當欄位$desc不為空時才執行插入)。 db_param="-h127.0.0.1 -uigame -pigame_admin" while r
  • 指針即地址。 1. 指針與變數。 2. 指針與數組。 3. 指針與字元串。 4. 指針與函數:指針函數(返回值為指針的函數)與函數指針(指向函數的指針)。 5. 指針數組與指向指針的指針。 6. 關於二維數組的指針 當我們定義int a[3][4] ;int (*p)[4]; 時,這時 p 與 a
  • 1 <?xml version="1.0" encoding="gbk"?> 2 <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="ehcache.xsd"> 3
  • Linux shell腳本編程(二) 1 練習:求100以內所有偶數之和; 2 使用至少三種方法實現; 3 4 示例1: 5 6 #!/bin/bash 7 # 8 declare -i sum=0 #聲明一個變數求和,初始值為0 9 10 for i in $(seq 0 2 100); do 1
  • 大眾點評的老吳在InfoQ上講了Cat之後,有不少同仁開始關註這個實時監控系統,但學習的文章甚少,在GitHub上也是一言代過,給我們這些開發人員留下了N多個疑問,一時間不知道去哪裡問,向誰去問了,通常的百度和谷歌也不好使了,不過,好在經理推薦的QQ群幫了忙,認識了一些cat的前輩,經過他們的努力和
  • 1 package com.shejimoshi.behavioral.ChainOfResponsibility; 2 3 4 /** 5 * 功能:問題類型 6 * 時間:2016年3月1日上午9:59:18 7 * 作者:cutter_point 8 */ 9 public enum Ques
  • 說明:信息系統實踐手記系列是系筆者在平時研發中先後遇到的大小的問題,也許朴實和細微,但往往卻是經常遇到的問題。筆者對其中比較典型的加以收集,描述,歸納和分享。 摘要:介紹典型的客戶端中列表數據展現的6個要素。 正文 1.客戶端和伺服器 一般典型的信息系統總可以分為前臺(也稱“客戶端”)和後臺(也稱“
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...