MATLAB 使用 GPU 加速計算總結

2022-01-02 運維感知

一、GPU 檢測

 % 檢測 GPU 數量
 gpuDeviceCount("available")
 % 列出 GPU
 gpuDeviceTable

在最後輸出信息中的最後一列可以看到該 GPU 沒有被選擇

設置 GPU,並查看 GPU 的屬性

該設備已被成功選擇

檢測是否具有支持的 GPU 可用於計算,輸出為1表示有

 tf = canUseGPU()

其他查詢屬性的相關命令

 % 創建默認 GPU 設備的對象,即查詢當前顯卡信息
 D = gpuDevice;
 % 查詢所有可用的 GPU
 for ii = 1:gpuDeviceCount
        D = gpuDevice(ii);
       fprintf(1,'Device %i has ComputeCapability %s \n', ...
       D.Index,D.ComputeCapability)
 end

二、運算測試

1、下面進行將運算傳遞 GPU 進行簡單的測試

 % 使用gpuArray功能將其發送到 GPU
 A = gpuArray([1 0 1; -1 -2 0; 0 1 -1]);
 % 返回一個列向量,其中包含方陣 A 的特徵值
 e = eig(A);
 % 列印輸出結果
 fprintf("%i \n",e);

輸出結果

 8.019377e-01
 -2.246980e+00
 -5.549581e-01

2、創建一個1000 × 1000的 gpuArray 的 randn 值  

 G = randn(1000,'double','gpuArray');
 G

可以正常輸出結果,沒有問題。經過查閱資料,大部分數據生成類函數可以添加 'gpuArray' 參數就可實現 GPU 計算,還有一部分運算類函數或值可以通過 gpuArray 包含其他函數實現,還有深度學習中也有其他不同的方法實現,另外 gather 函數可以將 GPU 數據回傳給 CPU。

主要步驟有以下兩步:

將數據從 CPU 中搬入 GPU,M = gpuArray(M)

在GPU中計算完成後,將數據搬出到 CPU 存儲,例如 M = gather(M)

例如下面求解一個線性方程組使用 gpuArray( ) 方式

 tf = canUseGPU()
 % 在 CPU 上創建數據。
 N = 1000;
 A = rand(N);
 b = rand(N,1);
 % 將矩陣 A 傳輸到 GPU(如果有可用的 GPU)
 if tf
       A = gpuArray(A);
 end
 % 求解線性方程組
 x = A\b;

支持 GPU 的機器學習函數連結:

https://ww2.mathworks.cn/help/stats/referencelist.html?type=function&capability=gpuarrays

支持 GPU 的深度學習函數連結:

https://ww2.mathworks.cn/help/deeplearning/referencelist.html?type=function&capability=gpuarrays

但是有一個小問題是它和原生的 rand 生成的結果不一樣,查閱官網發現它們之間的算法調度不一樣導致的,共有三種隨機數生成器算法。

 >> rand(1,4)
 ans =
  0.8147 0.9058 0.1270 0.9134
 >> rand(1,4,'gpuArray')
 ans =
  0.4320 0.3710 0.1217 0.7504

若非要和原生 rand 函數使用的隨機數算法一致可以通過下面方式進行解決:分別使用 rng (控制隨機數生成器) 和 gpurng (控制 GPU 計算的隨機數生成) 在 CPU 和 GPU 上設置生成器算法和種子

 % 原生 rand
 sc = rng(1,'Threefry');
 Rc = rand(1,4)
 
 % GPU rand
 sg = gpurng(1,'Threefry');
 Rg = rand(1,4,'gpuArray')

輸出結果

 Rc =
  0.1404 0.8197 0.1073 0.4131
 Rg =
  0.1404 0.8197 0.1073 0.4131

官方提到也可以人工控制,暫時先了解這麼多。

3、官方提供的測試代碼

 % 生成 GPU 上常用的分布隨機數字的數據集
 dist = randn(1e5,1e4,"gpuArray");
 % 確定是否為 GPU 陣列dist
 TF = isgpuarray(dist)

提示我內存不足,我一開始怎麼也不相信……,事實證明我高估我的顯卡能力了,將值的範圍改小就能行的通了

 Create a 1000-by-1000 gpuArray of randn values with underlying class double
 Out of memory on device. To view more detail about available
 memory on the GPU, use 'gpuDevice()'. If the problem persists,
 reset the GPU by calling 'gpuDevice(1)'.

我這裡改成了 1000 × 1000

 dist = randn(1e3,1e3,"gpuArray");

確定是否為 GPU 陣列 dist

 >> TF = isgpuarray(dist)
 TF =
  logical
  1

使用 GPU 陣列輸入參數執行功能。例如,計算每個列中的樣本偏斜度。由於是 GPU 陣列,因此該功能會在 GPU 上執行,並將結果作為 GPU 陣列返回。

 skew = skewness(dist);
 % 驗證輸出是否為 GPU 陣列
 TF = isgpuarray(skew)

輸出結果

 TF =
  logical
  1

三、評估 GPU 執行速度

評估 GPU 上的功能執行時間,並將性能與 CPU 上的執行進行比較。如果一個函數具有 gpuArray 支持,隨著觀測次數的增加,GPU 上的計算通常會比 CPU 更具性能。

使用 gputimeit (並行計算工具箱)功能在幾秒鐘內測量功能運行時間。優於使用 GPU 的功能,因為它可確保操作完成並補償間接費用。

下面在 GPU 上計算一個很大的值,其中是 12000 乘 400 矩陣,即 400 乘 12000

 A = rand(12000,400,'gpuArray');
 B = rand(400,12000,'gpuArray');
 f = @() sum(A.' .* B, 1);
 t = gputimeit(f)

輸出結果。可以看到處理時間是非常快的。

 t =
  0.0013

CPU VS GPU

 %% 用CPU進行計算
 num = zeros(101,1);
 A = randn(1e5,1,'single');
 f = @() filter(num,1,A);
 timeit(f)
 
 %% 用GPU進行計算
 A_gpu = randn(1e8,1,'single','gpuArray');
 num_gpu = gpuArray(num);
 f_gpu = @() filter(num_gpu,1,A_gpu);
 gputimeit(f_gpu)

輸出結果

 ans =
  7.7344e-04
 ans =
  0.0170

現在有個問題是當矩陣維數比較小的時候,GPU 計算速度並沒有CPU 計算速度快,只有當矩陣維數比較大的時候,GPU 才有加速效果,測試代碼如下

   clear all

 clc
 M = rand(5, 5);
 % 下面維度越大,GPU 的運算優勢越能凸顯出來
 % M = rand(50, 50);
 % M = rand(500, 500);
 % M = rand(5000, 5000);
 
 tt1 = 0;
 for i = 1:1000
      tic
      N = M .* M;
      t1 = toc;
      tt1 = tt1 + t1;
 end
 tt1
 
 M = gpuArray(single(M));
 tt2 = 0;
 for i = 1:1000
      tic
      N1 = M .* M;
      t2 = toc;
      tt2 = tt2 + t2;
 end
 tt2

輸出結果

 tt1 =
  8.6960e-04
 tt2 =
  0.0121

我下面接著循環 2000 × 2000 的矩陣,進行比對後發現,大約在 500 × 500 左右差距越來越來大,結果如下圖所示。

測試平臺(筆記本):

若你的訓練的數據集數據量維度大,一般選擇在 GPU 上跑就行,若維度較小,有一列或行低於 500 就沒有必要了。

四、CPU 代碼轉 GPU 代碼進行實測

實測修改張濱碩士 code1 代碼後將數據傳遞到 GPU 上運算運算速度會慢許多,因為數據的維度太小,下面是時間損耗的差別。

GPU 上運算

CPU 上運算

GPU 時間開銷要比 CPU 大 7 倍左右,那這代碼不如不改了……,所以數據量不大,就不要用 GPU 了,學生機的 GPU 內存一般也比較小,當數據量太大時,也可能會出現一定的問題。

當我看到 code3 代碼時眼前一亮,這就是我一直要找的測試數據,這裡的圖片數據是一種稀疏矩陣的數據,目前暫時 MATLAB 的 gpuArray 不適用,這個問題在 15 年就有人反映過了,但是官方一直沒有更新,我在 Git 上找到一個 gpuSparse 工具,貌似可以實現,但是我調試了一會沒有成功。下面我將除了 sparse double 類型的其他高維度數據傳到 GPU 上運算,效果馬上就上來了,若是能解決 sparse double 問題,應該會更棒,下面是測試結果:

未修改前 CPU 上運算

修改後 GPU 上運算

當我測試另個一訓練層時,訓練速度更快了:

我是拿了其中的幾個小的訓練層做的測試,第一個測試內循環中 GPU 每個小循環平均不超過 0.02s,GPU 的運算時間相比 CPU 縮短了 3.5 倍, 這個 code3 我最開始跑大概用了 20 個小時,如果機器和代碼都穩定的話總訓練時間至少會降到 7 小時,終於可以節約時間了……,CPU 不會有被棧滿的情況發生了 ,不用擔心因為電腦太卡導致 Explore 奔潰了,下圖是我之前訓練過程中 CPU 的佔用情況,電腦除了訓練外,不能做別的事情。

現在的 CPU 佔用率降到了 26%(平均)

現在的 GPU 利用率 86%

CPU 被解放後,普通軟體桌面窗口所需的 GPU 資源有限,此時電腦也可做更多的事情。

不過代碼穩定性肯定還存在缺陷,因為這個程序的代碼過於複雜,代碼量和函數調用都挺多的,一旦某個地方出現了小問題有可能需要大改動,也有可能改了很久後也沒有解決,這些都很正常。

五、總結

實現起來不複雜,有能力可以嘗試一下,萬一節約了一半的時間也是很賺的

數據量小,數據維度小沒必要放在 GPU 上,CPU 計算更快。

代碼量龐大和複雜的程序一般也不要寫成或改成在 GPU 上運行的程序,還是 CPU 版本的穩定,慢些就慢些吧……

遇到 sparse 類型的數據一般不要改動了,官方都沒有實現其 GPU 上計算,可能是有一定的缺陷的。

有些算法中用 gpuArray 函數運算速度可能會變快,也可能會變慢,需要自己調試,比如 code3 中我將激活函數 sigmod 的計算放到 GPU 上變慢了……

並不是所有的數據集合都是需要添加 gpuArray 參數,參與運算的一個重要數據集使用了 gpuArray 參數,那麼相關聯計算的數據集就不再需要額外添加了。

靈活使用 gather 函數回調會讓程序跑的更快,將低維度的大數據量回調到 CPU 上計算更快。

相關焦點

  • GPU中的並行運算,加速你的Matlab程序
    Matlab本就擅長矩陣計算,其藉助CUDA工具箱調用Nvidia GPU加速並行運算,可以起到如虎添翼的效果。
  • 科學計算 Matlab 使用 GPU 並行計算
    早在2001年左右,便有人提出了基於GPU的通用計算(General-purpose computing ongraphics processing units, GPGPU)的概念,利用GPU的強大的並行計算能力和相對的低功耗來加速科學計算。基本思路是把需要計算的數據打包成GPU可以處理的圖像信息,然後利用處理圖像信息的運算來實現科學計算。
  • 用GPU進行TensorFlow計算加速
    為了加速訓練過程,本文將介紹如何如何在TensorFlow中使用單個GPU進行計算加速,也將介紹生成TensorFlow會話(tf.Session)時的一些常用參數。通過這些參數可以使調試更加方便而且程序的可擴展性更好。
  • matlab程序加速與優化
    以及:https://blog.csdn.net/renxingzhadan/article/details/70212948問題我用matlab做了一個優化的程序,調用comsol來進行計算,但是運行時間較長,我用實驗室的伺服器進行計算,但是一晚過後matlab的計算速度漸漸變慢,最後竟然停止了運算,請問各位大俠,這是個怎麼個問題啊?
  • Matlab和Python結合使用
    Matlab 和 Python 結合使用無非分為兩種情形:(1)Matlab中使用Python;(2)Python中使用Matlab。比如,我們在 anaconda3 中除了基本環境 base 之外,還有個 pytorch-gpu的環境,而這個環境一般會在anaconda3安裝路徑下的 envs 文件夾中,因此通用的路徑是:.
  • FLUENT計算與GPU加速
    過去,如果要搞深度學習,或者數值計算系統求解的GPU加速,通常只能使用專用計算卡,包括Quadro系列、Tesla系列等。然而,隨著皮衣刀客黃仁勳發布30系顯卡,旗艦卡3090有著比TITAN更高的性價比,過去「四路泰坦抱回家」的梗總算能改成「3090抱回家」了。
  • 32個實用matlab編程技巧
    今天給大家介紹一些編程小技巧,之前給大家介紹過matlab編程小技巧,本期是在之前的基礎之上做了修正和補充完善,下面一起來看看吧。1、能用矩陣計算的就用矩陣計算,不能用矩陣計算的想方設法也要往矩陣計算上靠。2、少用循環,尤其是避免多重循環嵌套,儘量用向量化的運算來代替循環操作。
  • 【前沿】如何在 GPU 上加速數據科學
    【導讀】我們認為使用大型模型架構和相同數據在XLNet 和BERT之間進行公平的比較研究具有重要的科學價值。數據科學家需要算力。無論您是用 pandas 處理一個大數據集,還是用 Numpy 在一個大矩陣上運行一些計算,您都需要一臺強大的機器,以便在合理的時間內完成這項工作。
  • Matlab下直接使用GPU並行計算(預告)
    這是,在太陽-地月質心ERTBP和地球-月球CRTBP拼接模型下手動搜索到的一條深空探測中使用的很特殊的轉移軌道給點提示,其實把一段程序(比如這種使用了ode45的自身算法,還涉及到模型切換條件判斷)修改使運行在GPU上,關鍵只要明白Matlab可以在GPU上調用哪些函數即可,而這些在document裡面寫得相當清楚,但有些晦澀。在document中描述了兩類函數:支持gpuArray類型變量的函數,和可以在GPU上直接運行的函數。
  • 使用GPU.js改善JavaScript性能
    當你要執行複雜的計算時,實質上是將這種負擔轉移給系統的GPU而不是CPU,從而增加了處理速度和時間。高性能計算是使用GPU.js的主要優勢之一。如果你想在瀏覽器中進行並行計算,而不了解WebGL,那麼GPU.js是一個適合你的庫。為什麼要使用GPU.js為什麼要使用GPU執行複雜的計算的原因不勝枚舉,有太多的原因無法在一篇文章中探討。
  • 實戰Google深度學習框架:TensorFlow計算加速
    為了加速訓練過程,本章將介紹如何通過TensorFlow利用GPU或/和分布式計算進行模型訓練。本文節選自《TensorFlow:實戰Google深度學習框架》第十章。本文將介紹如何在TensorFlow中使用單個GPU進行計算加速,也將介紹生成TensorFlow會話(tf.Session)時的一些常用參數。通過這些參數可以使調試更加方便而且程序的可擴展性更好。
  • Matlab並行計算 GPU加速 視頻教程Part4~6
  • GPU加速02:超詳細Python Cuda零基礎入門教程,沒有顯卡也能學!
    使用Numba進行GPU編程,你可以享受:Python簡單易用的語法;極快的開發速度;成倍的硬體加速。Numba並不能加速程序,有可能速度更慢,而且在模擬器能夠運行的程序,並不能保證一定能在真正的GPU上運行,最終還是要以GPU為準。
  • 教程 | 如何在Julia編程中實現GPU加速
    對於大型數組,通過將計算轉移到 GPU,可以穩定地將速度提高 60-80 倍。獲得此加速和將 Julia 數組轉換為 GPUArray 一樣簡單。這些 gpu 數組的 Julia 操作由 Julia 的 GC 跟蹤,如果不再使用,GPU 內存將被釋放。因此,只能在設備上使用堆棧分配,並且只能被其他的預先分配的 GPU 緩衝區使用。由於轉移代價很高,因此在編寫 GPU 時,往往要儘可能重用和預分配。
  • 啟用Docker虛擬機GPU,加速深度學習
    為了解決這一兼容問題,就有必要使用到虛擬機,現在很多開源項目都會提供一個虛擬機文件,裡面包含了所有項目所需的軟體包和環境。GPU加速接下來說一下GPU加速。使用Docker虛擬機解決了開發環境問題,但同時又引入了另一個問題:虛擬機通常無法啟用GPU。
  • 學習模板分享(含微積分matlab計算模版)
    大家好,之前花費了很多時間去學習總結和matlab仿真,在B站也發布了很多學習視頻,參考來源有B站此夢千尋、刀摩根等人
  • 英特爾MKL加速AMD計算可達3倍?AMD Yes
    數學計算中的硬體加速是社區經常探討的話題,如果能夠利用一些庫和硬體的優勢,無疑能夠幫助科研、生產等。
  • GPU加速03:多流和共享內存—讓你的CUDA程序如虎添翼的優化技術!
    超詳細Python Cuda零基礎入門教程:主要介紹了CUDA核函數,Thread、Block和Grid概念,內存分配,並使用Python Numba進行簡單的並行計算。閱讀完前兩篇文章後,相信讀者應該能夠將一些簡單的CPU代碼修改成GPU並行代碼,但是對計算密集型任務,僅僅使用前文的方法還是遠遠不夠的,GPU的並行計算能力未能充分利用。
  • 當GPU加速計算遇上傳統數據中心……
    451 Research的分析師Jason Stamper表示,他們的並行架構使它們非常適合一些可以受益於GPU加速計算的傳統工作負載。「由於GPU具有數千個內核,並為在大屏幕上處理圖形的分秒運動而設計,如果將其指向行和列數據,那麼在進行分析處理方面的速度就會非常快,」Stamper說。當CPU時速每兩年翻一番時,對GPU加速計算能力的速度幾乎沒什麼要求。
  • Matlab使用技巧總結-1
    2.1 pre-allocation提高運算速度雖然matlab是動態語言,但是【預先分配變量】可以明顯提高運算速度。例如:section1中預定義了A = zeros() ,比 section2 的運算速度快了近40倍。