日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

将Tensor核心引入标准Fortran

發布時間:2023/11/28 生活经验 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 将Tensor核心引入标准Fortran 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

將Tensor核心引入標準Fortran
調優的數學庫是從HPC系統提取最終性能的一種簡單而可靠的方法。但是,對于壽命長的應用程序或需要在各種平臺上運行的應用程序,為每個供應商或庫版本調整庫調用可能是維護的噩夢。
可以自動生成對調優數學庫的調用的編譯器為提供了兩全其美的優勢:易于移植和終極性能。在本文中,將展示如何在GPU上無縫加速許多標準Fortran數組內在函數和語言構造。nvfortran編譯器通過將Fortran語句映射到NVIDIA cuTENSOR庫中的可用功能來自動啟用此加速,該庫是NVIDIA cuTENSOR的先河,提供GPU加速的張量線性代數庫,提供張量收縮,縮小和逐元素運算。
輕松過渡到NVIDIA GPU
以下是標準Fortran數組內在函數如何映射到GPU加速的數學庫。在最簡單的級別上,只需要兩個Fortran語句即可利用cuTENSOR庫提供的出色性能:
使用cutensorex

c = matmul(a,b)
使用cutensorex預定義模塊的第一條語句以重載的Fortran內在過程,數組表達式和重載的賦值形式包含cuTENSOR庫的接口。編寫接口以僅映射位于GPU設備內存中的陣列。在本文的稍后部分,將從OpenACC和CUDA Fortran程序員的角度討論這意味著什么。定義了這些接口后,包含matmul()內部調用的第二條語句將自動映射到cuTENSOR函數調用。
這些接口通過識別并匹配可以映射到單個cuTENSOR內核調用的幾種常用模式來實現延遲執行。在所有情況下,都將調用多個cuTENSOR函數來設置cuTENSOR所需的句柄,描述符數據結構和工作緩沖區。
但是,只有一個內核被啟動到GPU。出于性能考慮,將整個語句(包括分配給左側數組)映射起來很重要。不希望編譯器為右側操作的輸入或結果(中間或最終)創建Fortran中常見的臨時數組。
支持的標準Fortran操作
cuTENSOR庫包含常規的排列和收縮操作。置換的結果可以可選地通過元素函數來操作,并且可選地縮放。
nvfortran編譯器可以識別和映射與通用數組語法結合使用的各種Fortran轉換內在函數和基本內在函數,并將其映射到cuTENSOR功能。一些更直接的翻譯包括:
d =轉置(a)
d =函數(transpose(a))
d = alpha * func(轉置(a)

d =重塑(a,shape = […])
d =重塑(a,shape = […],order = […])
d =函數(reshape(a,…))
d = alpha * func(reshape(a,…))

d =點差(a,dim = k,ncopies = n)
d =函數(spread(a,dim = k,ncopies = n))
d = alpha * func(spread(a,dim = k,ncopies = n))
matmul()也可以在cuTENSOR中排列to的輸入,并且可以縮放和累加結果。這導致幾種可能的組合,例如以下語句:
c = matmul(a,b)
c = c + matmul(a,b)
c = c-matmul(a,b)
c = c + alpha * matmul(a,b)
d = alpha * matmul(a,b)+ beta * c

c = matmul(轉置(a),b)
c = matmul(reshape(a,shape = […],order = […]),b)
c = matmul(a,轉置(b))
c = matmul(a,reshape(b,shape = […],order = […]))
使用標準Fortran中的NVIDIA Tensor Core
當使用cutensorex模塊中包含的用于隨機數生成的功能時,利用cuTENSOR和NVIDIA Tensor Core就像下面的代碼示例一樣容易:
程序主體
使用cutensorex
整數,參數:: ni = 5120,nj = 5120,nk = 5120,ntimes = 10
實數(8),可分配,尺寸(:,😃 :: a,b,d
分配(a(ni,nk),b(nk,nj),d(ni,nj))
呼叫random_number(a)
呼叫random_number(b)
d = 0.0d0

  打印*,“裁切器”呼叫cpu_time(t1)做nt = 1,ntimesd = d + matmul(a,b)做完呼叫cpu_time(t2)拖鞋= 2.0 * ni * nj * nk翻牌=翻牌* n次打印*,“ times”,t2,t1,t2-t1打印*,“ GFlops”,flops /(t2-t1)/1.e9結束程序

該matmul()固有調用映射到cuTENSOR調用,無縫地使用張量核盡可能。將在本文后面顯示一些性能結果。
使用nvfortran編譯程序
可能會問, cutensorex接口僅將GPU設備陣列上的操作映射到cuTENSOR調用時,該程序如何使用cuTENSOR 。答案在于程序的編譯方式:
%nvfortran -acc -gpu =托管-cuda -cudalib main.f90
在這里,將程序編譯為OpenACC程序,并利用OpenACC托管內存模式,在該模式下,所有可分配陣列都分配在CUDA統一內存中。由于增加了-cuda,使CUDA Fortran擴展為好,數組實質上CUDA Fortran語言-管理型陣列。CUDA Fortran通用接口匹配的一條規則是,當主機和設備接口同時存在時,優選使用設備接口作為托管實際參數。
當聲明,分配和使用位于同一程序單元中時,nvfortran編譯器提供一些快捷方式。通常,最好使用OpenACC指令來指示編譯器傳遞設備地址,如以下代碼示例所示:
!$ acc host_data use_device(a,b,d)
做nt = 1,ntimes
d = d + matmul(a,b)
做完
!$ acc結束host_data
在這種情況下,-cuda不需要編譯器選項。
使用CUDA Fortran中的cuTENSOR
對于CUDA Fortran用戶而言,cutensorex模塊和Fortran轉換內在函數成為獲取高性能和完全可移植代碼的快速途徑。使用!@cuf前哨添加由nvfortran CUDA Fortran編譯器解釋和編譯的代碼行,或由標準Fortran編譯器作為注釋忽略的代碼行:
程序主體
!@cuf使用cutensorex
!@cuf使用cudafor
整數,參數:: ni = 5120,nj = 5120,nk = 5120,ntimes = 10
實數(8),可分配,尺寸(:,😃 :: a,b,d
!@cuf屬性(設備):: a,b,d
分配(a(ni,nk),b(nk,nj),d(ni,nj))
呼叫random_number(a)
呼叫random_number(b)
d = 0.0d0

  打印*,“裁切器”呼叫cpu_time(t1)做nt = 1,ntimesd = d + matmul(a,b)做完呼叫cpu_time(t2)拖鞋= 2.0 * ni * nj * nk翻牌=翻牌* n次打印*,“ times”,t2,t1,t2-t1打印*,“ GFlops”,flops /(t2-t1)/1.e9結束程序

在第6行,使用設備屬性聲明了數組,將其放置在GPU設備內存中。但是,也可以使用托管屬性來聲明它。可以編譯該程序并將其與以下命令鏈接:
%nvfortran -Mcudalib main.cuf
實測(8)數據的性能
下面是從前面示例中使用的real(8)(雙精度)數據開始的性能觀察。可以通過以下幾種方法來衡量矩陣乘法性能:
? 單線程CPU實現
? 多線程或多核CPU實現
? 天真編碼矩陣乘法使用指令分載
? 該matmul()映射到cuTENSOR內在
為了獲得最佳的線程CPU性能,請使用基本的線性代數子程序(BLAS)庫例程DGEMM。以下命令與先前操作的等效DGEMM調用:
呼叫dgemm(‘n’,‘n’,ni,nj,nk,1.0d0,a,ni,b,nk,1.0d0,d,ni)
為了了解經過調整的庫可以通過天真的實現提供什么,使用以下OpenACC循環結構在GPU上運行。循環結構不使用特殊的拼貼或硬件指令。
$ acc內核
做j = 1,nj
是否等于1,ni
做k = 1,nk
d(i,j)= d(i,j)+ a(i,k)* b(k,j)
做完
做完
做完
$ acc結束內核
表1顯示了real(8)在基于雙插槽AMD EPYC 7742 Rome CPU的服務器,單個NVIDIA V100和單個NVIDIA A100 GPU的一個NUMA節點上獲得的性能。

表1.雙插槽AMD EPYC 7742 Rome基于CPU的服務器,單個V100和單個A100 GPU在一個NUMA節點上的real(8)性能。
不僅可以使用matmul()固有函數在V100和A100 GPU上獲得自動GPU加速,而且在A100上matmul()到cuTENSOR調用的映射可以使自動使用FP64 Tensor Core。
在real(4)和real(2)數據上測得的性能
可以使用real(4)(單精度)數據并調用SGEMM而不是DGEMM來執行同一組運行。此外,CUDA 11.0 cuTENSOR Fortran包裝器可以利用A100 TF32數據類型和Tensor Core。表2顯示了這些運行的性能。

表2.雙插槽AMD EPYC 7742 Rome基于CPU的服務器,單個V100和單個A100 GPU的一個NUMA節點上的real(4)性能。
為什么停在那里?nvfortran編譯器使用real(2)數據類型支持16位浮點格式(FP16)。可以在較早的測試中更改數組的類型,并以半精度運行計時。
Tensor Core操作是在V100上引入的,用于半精度數據,然后在A100 GPU上進行了擴展,以支持TF32和完整的雙精度DP64 Tensor Core。盡管nvfortran支持real(2)V100和A100上的Tensor Core,但它不支持real(2)CPU上的完整和優化,標準BLAS庫也不支持。在這種情況下,只有比較GPU加速版本的性能才有意義(表3)。

表3.單個V100和單個A100 GPU的real(2)性能。
盡管A100的性能令人印象深刻且代碼可完全移植,但它遠低于TF32和FP16的峰值。有固定的開銷:在每個調用中,創建并銷毀cuTENSOR張量描述符并創建收縮計劃。還必須查詢和管理收縮中使用的工作空間要求,這最終可能會調用cudaMalloc和cudaFree。如果FP64的開銷為5 – 10%,則對于這種大小的問題,TF32的開銷將接近25%,FP16的開銷將接近35%。
對于需要最終性能的開發人員,nvfortran確實支持HPC SDK中也提供的Fortran cutensor模塊中與C cuTENSOR API的Fortran接口。可以自己管理張量描述符,計劃和工作區。
結論
在本文中,展示了一些簡單的程序以及可以在GPU上自動加速的Fortran內部調用和代碼模式的類型。甚至可以通過cuTENSOR自動利用Tensor Core。使用幾乎完全是Fortran標準的程序并完全可移植到其編譯器和系統的程序,可以在NVIDIA GPU上實現矩陣乘法,矩陣轉置,元素數組內在函數以及數組語法的多種組合的近峰性能。
無法預測使用這些新功能可能會做什么。期待著的反饋和結果。NVIDIA繼續添加更多功能,使可以使用標準的Fortran結構以最高的性能對NVIDIA GPU進行編程。

總結

以上是生活随笔為你收集整理的将Tensor核心引入标准Fortran的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。