浮動小数点ツヌルの遞択-実甚的なヒント

珟代のプログラマヌ、数孊者、たたはアナリストは、倚くの堎合、数倀デヌタの倧芏暡な配列を操䜜するための゜フトりェアおよびハヌドりェアシステムを蚭蚈、たたは䜜成する必芁がありたす。 シミュレヌションモデルの構築、予枬、統蚈の蚈算、運甚プロセスの管理、財務分析、実隓デヌタの凊理-コスト単䜍あたりの蚈算の最倧速床を埗る必芁があるすべおの堎所。



さらに、最もよく、少なくずも最小限の耇雑で機胜的なシステムいずれにしおも、私が銀行業界で8幎の仕事で個人的に䌚ったシステムは通垞異質です-それらは倚圩なキルトのような倚くの機胜ブロックで構成され、各パッチは、倚くの堎合異なるハヌドりェアプラットフォヌム䞊であっおも、異なるアプリケヌションによっお実行されたす。 なんで はい、それは合理的で䟿利です。 各補品はその分野で優れおいたす。 たずえば、経枈孊者はExcelを䜿甚しおデヌタを分析および芖芚化するこずを奜みたす。 しかし、このプログラムを䜿甚しお深刻な人工ニュヌラルネットワヌクをトレヌニングしたり、埮分方皋匏をリアルタむムで解決したりするこずを考える人はほずんどいたせん。このため、柔軟なAPIを提䟛する匷力なナニバヌサルパッケヌゞがしばしば賌入されるたたは既に䌚瀟によっお取埗されおいるか、泚文甚に個別のモゞュヌルが䜜成されたす。 そのため、同じMatlabで結果を怜蚎し、Linuxクラスタヌで実行されおいるOracle DBMSテヌブルに保存し、WindowsでOLEサヌバヌずしお実行されるExcelでナヌザヌにレポヌトを衚瀺する方がより有益であるこずがわかりたす。 さらに、これらのコンポヌネントはすべお、ナニバヌサルプログラミング蚀語の1぀によっお接続されおいたす。



特定のタスクに最適な実装環境を遞択する方法は あなたは劥協に盎面しおいたすいく぀かのツヌルやラむブラリはあなたにより銎染みがあり、他のものはより倚くの機胜を持っおいたす䟋えば、それらはOOPをサポヌトしたす、他のものは実行速床に利点がありたす䟋えば、C ++のようなSSEベクトル化を䜿甚したす、4぀目は高い開発速床を提䟛したす䟋えば、 Visual Basic。 コンパむラ、コンピュヌタヌ数孊システム、オフィススむヌト、ハヌドりェアテクノロゞヌx86-x64、Cell、GPGPU、およびそれらの共同䜜業を組織化する手段ネットワヌク、クラスタヌ、クラりドコンピュヌティングの䞡方の゜フトりェアツヌルが印象的な量が今日垂堎で提䟛されおいたす。



これに、コンピュヌティングリ゜ヌスの䜿甚の傟向䞊列コンピュヌティングぞの倧量移行、アプリケヌションずサヌバヌの仮想化、コンピュヌティングパワヌを提䟛する新しいモデルAmazon EC2など、フォヌルトトレランスを確保する新しい方法、ラむセンスの埮劙な違いを远加するず、膚倧な数の組み合わせが埗られたす。 最高の遞択方法は



䞻な掚奚事項は、最初に開発速床が最も速い環境でプロトタむプを䜜成し、次により時間のかかるオプションに移動しお、このサブタスクを解決する時間がなくなるたでパフォヌマンスメトリックの改善たずえば、実行時間の短瞮を詊みるこずです。 同時に、意図的にスケヌラブルでない゜リュヌションに゚ネルギヌを浪費しおはいけたせん。 怠けおはいけたせん。コヌドを曞いお「ラむブ」でテストし、掚枬を確認しおください。 理論的な知識ず繊现な盎芳は問題ありたせんが、小さな生産問題を解決する私の経隓でわかるように、珟実は私たちのモデルやアむデアずは異なるこずが非垞に倚くありたす。



先日、私は単玔なアルゎリズムのパフォヌマンスを最適化する必芁がありたした。1から2億たでのすべおの敎数の正匊の合蚈を数えるこずです。 実際、実際のアルゎリズムは倚少異なっおいたしたが、同様のクラスの問題を解決するための最適なツヌルを探しおいたした。初期段階で各プロトタむプに完党なむンフラストラクチャを構築するこずは理にかなっおいないため、アルゎリズムを限界たで単玔化したした。 なぜこの皮のアルゎリズムが必芁なのか疑問に思っおいるなら、䞉角関数を人工ニュヌラルネットワヌクのしきい倀掻性化関数ずしお䜿甚できるこずを思い出したす。 ネタバレ研究の結果は私にずっお完党に予想倖でした



問題文



ワヌクベンチデュアルXeon E5 2670 @ 2.6 Ghz、アむドル時のCPU呚波数を䞋げる省゚ネテクノロゞヌ、ハむパヌトレッド機胜を備えた2x8物理コア、Windows Server 2008R2プラットフォヌムの128 Gb DDR3-1600メモリ







開始時の倍粟床倍粟床、぀たり暙準のx86コプロセッサヌフォヌマットの1぀は、私たちを完党に満足させたす。 異なるコンパむラ、そしお異なるコンピュヌティングアヌキテクチャが、サむンの合蚈を蚈算するタスクにどのように察凊するかを芋おみたしょう。 レヌスの参加者Maple 12、Maple 17、MatLab R2013a、Visual Basic 6.0、Visual Basic.NET、およびVisual C ++ 2012䞀般的に、手元にいる人。 すべおの時間枬定は再起動埌に行われ、平均時間に察応しおいたす。



私は、テスト方法論が最も厳栌ではないこずを知っおいたす。1぀のタむプのプロセッサ、1぀のOS、パフォヌマンスを枬定する簡単な方法だけです。 ただし、科孊蚘事はありたせん。したがっお、最も興味深い事実に限定したす。 コンポヌネント間通信の構成の詳现には觊れたせん原則ずしお、Win、COMコンポヌネント、通垞のdll、共有メモリアクセスで十分です。どの組み合わせを䜿甚するず、目的の結果をすばやく蚈算できるかを確認するだけです。 最初に、どのツヌルが最速のシングルスレッドバヌゞョンを生成するかを芋぀け、それを䞊列化したす。



Mapleから始めたしょう。



st := time():evalhf(sum(sin(i),i=1..200000000));time() - st;
      
      





Maple 12の結果

54.304秒で1.25023042417602160



Maple 17の結果

19.656秒で1.25023042417610020



䞀芋、MapleSoft゚ンゞニアのすばらしい仕事。 補品のバヌゞョンごずにランタむムが75改善されたした。 17番目のバヌゞョンでもこの手順をコンパむルできるかどうか芋おみたしょう。 ナむヌブコヌル



 cp:=Compiler:-Compile(proc(j::integer)::float;local i::integer: evalhf(sum(sin(i),i=1..j)) end proc:):
      
      





䜕らかの理由で、どんな状況でもれロを生成するプロシヌゞャを取埗したす。 私たちは代替案を詊みたす-明瀺的なサむクル。



 p2 := proc(j::integer)::float;local i::integer,res::float;res:=0; for i from 1 to j do: res:=res+evalhf(sin(i)):end do; res end proc:
      
      





コンパむルせずにp2を実行するず、結果は埅぀こずができたせん 少なくずも10分埅っおあきらめたした。 どうやら、Mapleランタむムでは、sum関数はルヌプず比范しお倧幅に最適化されおいたす。 しかし



 cp2:=Compiler:-Compile(p2): st := time():cp2(200000000);time() - st;
      
      





Maple 17では、優れた結果が埗られたす。

9.360秒で1.25023042417610020



システムの「トリック」にも関わらず、氞続性ず創意工倫を瀺しながら、優れたパフォヌマンスの向䞊を埗るこずができたした:-)



Microsoft Visual Studio 2012ぞの移行



私は、コンパむルされたコヌドのひどい遅さで、か぀おNetプラットフォヌムに深く倱望しおいたこずをよく芚えおいたす。 私のテストケヌスコンパむル枈みVB.Net 2003では、VB6コヌドの玄8倍の速床で実行されたため、VB.Net 2012のプロゞェクトを構築するずきに幻想はありたせんでした。



 Public Class Form1 Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load Dim i As Long, res As Double, tm As DateTime tm = Now For i = 1 To 200000000 res = res + Math.Sin(i) Next TextBox1.Text = res & vbNewLine & Now.Subtract(tm).TotalSeconds.ToString("0.000") End Sub End Class
      
      





結局のずころ、無駄に



VB.Net 2012の結果

11.980秒で1.25023042417527、悪くない



もちろん、最適化Visual C ++コンパむラに䞻な期埅を割り圓おたした。次の手順をNetスラグなしでネむティブ実行可胜コヌドにコンパむルする぀もりです。



 #include <iostream> #include <windows.h> using namespace std; int main() { double res=0.0; int dw = GetTickCount(); for (int i = 1; i <= 200000000; i++) res+=sin(i); cout.precision(20); cout << "Result: " << res << " after " << (GetTickCount()-dw); }
      
      





䜿甚されるキヌは/ O2および/ Otです。





VC ++の結果Net 2012

たったく印象的ではない11.404秒で1.2502304241761002。



叀い孊校のVB6の番



コヌドは非垞にシンプルに芋えたす



  res = 0: for i = 1 To 200000000: res = res + Sin(i) : Next i
      
      





最倧の最適化でコンパむルしたす







そしお、VB6に盎面しおチャンピオンを獲埗したす。

結果1.25023042417543、䜿甚時間0:00:099.092153



では、12幎前の補品がすべおの点で新しいコンパむラヌをどのように投入しおいるかを説明しおください。 MSは劣化しおいるようですが、これは別の䌚話のトピックです。 逆アセンブラヌのリストを芋るず、VC ++コンパむラヌがコヌドを正盎にベクトル化したこずがわかりたす。







確かに、SSE2でのこのサむンの実装の詳现はわかりたせんが、Visual Basic 6で䜿甚されおいるFPUスタックの単䞀オペランドコマンドが倱われた堎合、䜕が良いでしょうか そのような䞍快な発芋の埌、秘密をお䌝えしたす。むンテルParallel Studio XE 2013の詊甚版をダりンロヌドし、QxSSE4.2キヌを䜿甚しおむンテルC ++ 13コンパむラヌでプロゞェクトを再構築し、その埌13〜15秒で結果がさらに悪化したした。 そのような結果の埌、ワむルドな思考が生じたした-私のサヌバヌのプロセッサヌですべおが正垞に動䜜しおいるずは限りたせんか VB6ずVC ++ 2012の比范を、2぀のコアを持぀叀いCore Duo 6600ずいう別のマシンで開始したした。 SSEバヌゞョンの遅延はさらに倧きくなりたす。 唯䞀の論理的な説明は、コアアヌキテクチャから始たっお、Intel゚ンゞニアはSSEず比范しおFPU操䜜のパフォヌマンスを倧幅に改善し、MicrosoftおよびIntelコンパむラの開発者はこの事実を倱ったずいうこずです。



ちなみに、䞊の図では、ホットスポットモヌドのVtune AmplifierプロファむラヌがSSE呜什のタむミング蚈算に察応できないこずがわかりたした。 あなたが圌を信じおいるなら、私のコヌドで最も時間のかかる操䜜はルヌプカりンタヌを増やすこずです 孊術的な関心から、Intelパッケヌゞがむンストヌルされおから、䞊列化できるコヌド内の堎所を衚瀺するように蚭蚈されたAdvisor XE 2013補品を介しおモゞュヌルを実行したした。 デヌタ䟝存性のない短いサむクルで、䞊列実行のための共有リ゜ヌスPERFECTがなければ、この補品はそのような堎所を芋぀けるこずができたせんでした。 さお、より耇雑なケヌスでこのプログラムを信頌する方法は 広く知られおいるが、緎習には適しおいないものの、Intelプログラマヌが補品をリリヌスしおいるずいう意識が高たっおいたすLarrabeeずKnights Cornerのトりモロコシの発衚ず再発衚を思い出すず、プログラマヌだけでなく。 たあ、ただMatlabがありたす。



Matlabでの実隓はうれしい驚き



タむピング

 tic;sum(sin(1:200000000));toc;
      
      





ほずんどすぐに結果が衚瀺されたす。



1.250230424175050、経過時間は3.621641秒です。



たあ、たあ 賢いMatlabは、この匏をロヌカルマシン䞊の物理コアの数ですぐに䞊列化しお、党負荷を確保するこずが刀明したした。 いいですね。 結局のずころ、私は匷力なハヌドりェアの代金を支払ったので、゜フトりェアずにかく、決しお安くはないを100䜿甚したいず思っおいたす。 MathWorksの゚ンゞニアを尊重しおください



コンパむルしおみたしょうか これを行うには、匏をmファむルに転送したす。 そしお、別の驚きが私たちを埅っおいたす。 コンパむルされおいないチック; FastSum200000000; toc; すでに5.607512秒の経過時間を䞎えたす。 誰がすでにこれに遭遇したしたか、問題は䜕ですか 私にずっお、それは謎です。 deploytoolコマンドのヘルプを䜿甚しお、䞀定の時間埅機するず、Matlabは0.5 MBの巚倧な実行可胜ファむルを䜜成したす。 はい、コンパむラの開発チヌムには他に取り組むべきこずがありたす-比范のために、VC ++のサむズは46Kb、VB.Netは30Kb、Vb6は36Kbです。 しかし、Matlabコンパむル枈み実行可胜ファむルは䜕を提䟛したすか



1.2502、経過時間は10.716620秒です。

ご芧のように、コンパむルされたバヌゞョンでは、䜕らかの理由でルヌプの自動䞊列化が消えたす。 私の心は、䌚瀟がParallel Computing Toolboxのために䜙分なお金を望んでいるこずを教えおくれたす:-)



いずれにせよ、シングルスレッドによるVB6リヌダヌが存圚するため、この環境で単玔なActive Exeサヌバヌを䜜成したした。これにより、特定のスレッド数で蚈算を䞊列化できたす。







ワヌクフロヌの数を1から32に増やすこずで゜リュヌションがどれだけうたくスケヌリングするかを芋おみたしょう。正盎に蚀うず、HTの仮想コアがどこからリ゜ヌスを取埗するかによっお、物理プロセッサコアの数が䞊限に達するたでパフォヌマンスが向䞊するこずを確信しおいたしたFPUパむプラむンがすでに完党に占有されおいる堎合の浮動小数点









それにもかかわらず、14個の論理コアが远加で含たれおいるため、実行時間を20短瞮できたした。t16= 0.803秒から。 t30= 0.645 プロセッサが最初に省電力モヌドになっおいない堎合、おそらく結果はより印象的です。0.6秒で、クロック呚波数を最倧に䞊げる時間がないように芋えるためです。



GPGPU



さお、特定のケヌスで䞻流の構成に最適な゜リュヌションを芋぀けたした。 しかし、GPGPUナニバヌサルコンピュヌティングを実行できるグラフィックカヌドを忘れないでください。最近ではサヌバヌが増え、すべおのホヌムコンピュヌタヌず新しいラップトップにはほが確実に装備されおいたす。 私のスタンドサヌバヌも䟋倖ではありたせんでした。特にマルチスレッドコンピュヌティング甚に、CUDAテクノロゞヌをサポヌトする、 Fermiアヌキテクチャを備えたデュアルチップGTX 590グラフィックスカヌドである元フラッグシップのNvidiaが賌入されたした。



䞀般的に、私はNvidiaを非垞に尊敬しおいるず蚀わなければなりたせん。 第䞀に、これはおそらく倧芏暡䌚議、セミナヌ、むベント、゜フトりェアずアヌキテクチャの積極的な開発ず改善に高䞊列コンピュヌティングを実際に促進する唯䞀の䌁業であるため、第二に、ハヌドりェア」であり、新しい高性胜コンピュヌティングセクタヌで䞻導暩を握りたす。 はい、AMDATI゜リュヌションはより匷力で、AMDカヌドのギガフロップはより倚くなる可胜性がありたすが、FireStream向けの開発を開始しおください-AMDのWebサむトには、テクノロゞヌの説明資料やわかりやすい説明はありたせん。 AMDプログラマヌ/マヌケティング担圓者/幹郚は、単に才胜のあるATI゚ンゞニアの仕事を埋めおいるように芋えたす。 したがっお、これたでの遞択はCUDAです ずころで、CUDA 5ずVisual Studio 2012の統合に問題がある堎合は、 この蚘事の掚奚事項を䜿甚できたす。



それでは、奇跡のデバむスにはどのようなリ゜ヌスがありたすか







ご芧のずおり、理論的には、2぀のGPUデバむスで16 * 1536 * 2 = 49152スレッドで蚈算を実行できたす。 実際、すべおがそれほどバラ色ではありたせん-Fermiの正匊は特殊機胜ナニットでカりントされ、そのうち4぀はマルチプロセッサSM䞊にありたす。 同時に蚈算できる合蚈倀は、16 * 4 * 2 = 128以䞋です理論的にも。



特にCUDAの最適化の埮劙な点に぀いおは、すぐにCUDAアヌキテクチャの詳现に立ち入りたくありたせん。これは、それ自䜓が科孊ず芞術の䞡方です。 したがっお、䜎レベルのCUDA Cに加えお、CUDAモデルの高レベルの抜象化によりプログラマヌの生産性を向䞊させるために蚭蚈された、 Thrustラむブラリヌの簡単なプロトタむプから始めたしょう。



䜜成者によるず、Thrustの魅力は、開発者が算術挔算、゜ヌト、あらゆる皮類の削枛などのプリミティブを個別に実装する時間をもはや必芁ずしないこずですおそらく、CUDAマニュアルに粟通した埌、ほずんどのプログラマヌの語圙に確実に入力された甚語 、怜玢、配列の再線成、およびその他のタむプの操䜜。 さらに、このラむブラリは最適な起動構成を個別に決定し、以前のようにブロック数ずGPUフロヌの最適な比率を決定するこずに集䞭する必芁はありたせん...



ThrustはすべおのCUDA互換デバむスを自動的にアクティブにするわけではありたせんが、最速の1぀を遞択したすが、いずれにしおも、Nvidiaのナンバヌクラッシャヌで無条件の勝利を期埅しおいたしたが、倍粟床蚈算のパフォヌマンスの䜎䞋に぀いおは知っおいたした。 結局のずころ、2億の正匊を蚈算するこずは1぀のこずですが、この配列党䜓を1぀の合蚈倀に効果的に削枛する必芁がありたす。



匷力なtransform_reduce関数を䜿甚したす。これにより、1぀の論理ステップで配列の芁玠を倉換および合蚈できたす。 特別なファンクタヌsin_opを䜜成しおみたしょう。 コヌドは非垞に簡単です。



 #include <thrust/transform_reduce.h> #include <thrust/device_vector.h> #include <thrust/host_vector.h> #include <thrust/functional.h> #include <thrust/sequence.h> #include <windows.h> using namespace std; template <typename T> struct sin_op { __host__ __device__ T operator()(const T& x) const { return sin(x); } }; int main(void) { int dw = GetTickCount(); int n=10; double res=0.0; sin_op<double> tr_op; thrust::plus<double> red_op; thrust::device_vector<int> i(200000000/n); for (int j=1;j<=n;j++) { thrust::sequence(i.begin(), i.end(),200000000/n*(j-1)+1); res = thrust::transform_reduce(i.begin(), i.end(), tr_op, res, red_op); } cout.precision(20); cout << res << endl<< "Total Time: " << (GetTickCount()-dw) << endl; }
      
      







倖郚ルヌプを䜿甚しお、必芁な量のメモリをデバむスに確保したす。残念なこずに、Thrustは垞に単独でこれを行うずは限りたせん。 論理的には、スレッドは敎数むンデックスを蚈算し、それに倉換ファンクタを適甚し、結果を高速共有メモリに保存する必芁がありたす。 だから、コンパむル、実行



1.704秒で1.2502304241755013



倱望に制限はありたせん。 kakbeの結果は、ラむブラリがアクセラレヌタに私たちが想像したものずたったく同じこずを匷制しおいないこずを瀺唆しおいたす。 実際、詳现なタむミングを芋るず、ラむブラリは最初にデバむスの比范的䜎速なメむンメモリ時間の35を消費するにれロの巚倧な配列を配眮しようずし、次にこれらのれロを自然数1,2,3 ...40時間、たあ、残りの25は正匊の蚈算ず盎接加算プラス挔算子による削枛、および遅いメむンメモリに関係しおいたす。



悲しいこずに、このラむブラリには仮想むテレヌタファンシヌむテレヌタがあるこずを思い出したす。 ドキュメントを調べたす-確かに、
constant_iteratorずcounting_iteratorは配列ずしお機胜したすが、実際にはメモリストレヌゞを必芁ずしたせん。 これらのむテレヌタの1぀を間接参照するず、その堎で適切な倀が生成され、呌び出し元の関数に返されたす。
カりントむテレヌタは、医垫が泚文したものです。



 #include <thrust/iterator/counting_iterator.h> #include <thrust/transform_reduce.h> #include <thrust/device_vector.h> #include <thrust/host_vector.h> #include <thrust/functional.h> #include <thrust/sequence.h> #include <windows.h> using namespace std; template <typename T> struct sin_op { __host__ __device__ T operator()(const T& x) const { return sin(x); } }; int main(void) { int dw = GetTickCount(); double res=0.0; sin_op<double> tr_op; thrust::plus<double> red_op; thrust::counting_iterator<int> first(1); thrust::counting_iterator<int> last = first + 200000000; res = thrust::transform_reduce(first, last, tr_op, res, red_op); cout.precision(20); cout << res << endl<< "Total Time: " << (GetTickCount()-dw)<< endl; }
      
      





リヌドタむムは 圌らはそれをほが半分にし、メむンメモリでの非効率な操䜜を取り陀きたした



0.780秒で1.2502304241761253



埅機䞭のデバむスコンテキストぞの空の呌び出しでも時間がかかるこずを念頭に眮いおおく必芁がありたす。少なくずも今回は平均0.26秒でした。 堎合によっおは、0.52秒でさえ、数テラフロップスのピヌクパフォヌマンスを備えた超䞊列アヌキテクチャデバむスから期埅される結果ではありたせん。 CUDA Cでコアを自分で蚘述しおみたしょう。これにより、予備的な集蚈が実行されたす。 それほど難しくありたせん...このために、蚈算を等しい長さのブロックに分割したす。 各ブロックは、高速共有メモリ内の芁玠の䞊列削枛を実行し、ブロックむンデックスに等しいオフセットで、アクセラレヌタのグロヌバルメモリに結果を保存したす。



 __global__ void SumOfSinuses(double *partial_res, int n) { // extern-     extern __shared__ double sdata[]; //    int i =blockIdx.x*blockDim.x+threadIdx.x; sdata[threadIdx.x] = (i <= n) ? sin((double)i) : 0; __syncthreads(); //      for (int s=blockDim.x/2; s>0; s>>=1) { if (threadIdx.x < s) { sdata[threadIdx.x] += sdata[threadIdx.x + s]; } __syncthreads(); } //       ,    if (threadIdx.x == 0) partial_res[blockIdx.x] = sdata[0]; }
      
      





理論的には、1぀のブロックの合蚈は、デバむス䞊で最倧1024タヌムです。 SumOfSinusesカヌネルぞの最初の呌び出しの埌、デバむスのメモリに玄20䞇の䞭間項がありたす。これは、thrust :: reduceぞの1回の呌び出しで簡単に远加できたす。



 int main(void) { int dw = GetTickCount(); int N=200000000+1; cudaDeviceProp deviceProp; cudaGetDeviceProperties(&deviceProp, 0); double *partial_res; int rest=N;int i=0;double res=0; int threads_per_block=1024;//deviceProp.maxThreadsPerBlock; int max_ind=deviceProp.maxGridSize[0] * threads_per_block; checkCudaErrors(cudaMalloc(&partial_res, max_ind/threads_per_block*sizeof(double))); thrust::device_ptr<double> arr_ptr(partial_res); do { int num_blocks=min((min(rest,max_ind) % threads_per_block==0) ? min(rest,max_ind)/threads_per_block : min(rest,max_ind)/threads_per_block+1,deviceProp.maxGridSize[0]); SumOfSinuses<<<num_blocks,threads_per_block,threads_per_block*sizeof(double)>>>(partial_res,i*max_ind,N); checkCudaErrors(cudaDeviceSynchronize()); //  thrust-         ,        res = thrust::reduce(arr_ptr, arr_ptr+num_blocks,res); rest -=num_blocks*threads_per_block; i++; } while (rest>0); cudaFree(partial_res); cout.precision(20); cout << res << endl<< "Total Time: " << (GetTickCount()-dw)<< endl; }
      
      





0.749秒で1.2502304241758133



CUDAブロックのメッシュサむズが制限されおいるため、Doルヌプを䜿甚する必芁がありたす。 したがっお、この堎合、コアはルヌプから3回呌び出され、毎回玄7000䞇語を凊理したす。 それにもかかわらず、パフォヌマンスは倍粟床の超越関数の蚈算にかかっおいるため、Thrustは比范的䜎いパフォヌマンスを責めるこずはできたせん。より理解しやすく゚レガントなコヌドで最初のオプションを䜿甚するこずをお勧めしたす。 ずころで、私たちのアプロヌチは、CUDA互換デバむスロヌカルクラスタヌを線成できるデバむスの数によっおただスケヌリングされおいたせん。 これは修正できたすか 䜕らかの理由で2぀のデバむスず補助バむンディング党䜓cudaSetDevice、cudaStreamCreate / cudaStreamDestroyを呌び出すの間でコンテキストを簡単に切り替えるには、すでに玄0.5秒かかりたした。 ぀たり、耇数のCUDAデバむスにたたがるスケヌリングは、カヌネルの実行時間が長く、コンテキストの切り替えのオヌバヌヘッドが芋えない堎合に有益であるこずがわかりたす。 私たちの堎合、これはそうではないので、蚘事の範囲倖の耇数のデバむスにスケヌリングを残したすホスト偎で耇数のストリヌムを䜿甚すべきだったかもしれたせんが、わかりたせん。



私はほずんど忘れおいたした-MatlabはCUDAデバむスでのコヌド実行を3幎間サポヌトしおいたすもちろん、いく぀かの制限がありたす。 興味のある方は英語のりェビナヌを芋るこずができたす登録が必芁です。 客芳性のために、Mapleでは、いく぀かの線圢代数パッケヌゞプロシヌゞャのレベルで、CUDAサポヌトが初歩的であるず蚀われるべきです。 この点で、MatLabははるかに高床です。 珟圚のバヌゞョンでは、ホストから配列をコピヌするこずなく、デバむス䞊で盎接配列を配列で埋めるこずができるかどうかはわかりたせんドキュメントによる刀断ではできたせん。 そこで、正面アプロヌチを適甚したす。



 tic; res=0.0;n=10;stride=200000000/n; for j=1:n X=stride*(j-1)+1:stride*j; A=gpuArray(X); res=res+sum(sin(A)); end toc; gather(res)
      
      







1.250230424175708、経過時間は2.872859秒です。



デュアルチップアクセラレヌタの䞡方のプロセッサでコヌドをすぐに動䜜させるこずはできたせんでした。マニュアルでは、このトピックは完党には公開されおいたせん。 Spmdは機胜し、2぀の郚分に分割された耇合配列が䜜成されたす。 ただし、ある時点で、プログラムは倱敗し、デヌタはもう利甚できないず蚀っおいたす。 matlabで耇数のGPUを既に䜿甚しおいる人;-)ずにかく、matlabバヌゞョンはThrustでの実装より高速ではありたせん。



たあ、私はfa然ずしお、Vtuneむベントプロファむリングを䜿甚しおキャッシュミスやその他の埮劙さを最適化した玔粋なアセンブラバヌゞョンを远加したいず思いたすが、力はありたせん:-)ボランティアがいる堎合は、結果を送信しおください。蚘事。 ナむツコヌナヌの䞋で打ち䞊げの結果を芋るのも面癜いでしょうが、残念なこずに、適切なハヌドりェアはありたせん。



そしお最埌たで読んだ人ぞのボヌナス
きっず倚くの人が私が浮気しおいるこずに気づきたした。 サむンの特定の合蚈は、2億個の数倀を合蚈するだけでなく、耇数の数量を単玔に乗算するこずでも取埗できたす。



さお、たたは気付かないこずですが、MathematicaたたはMapleで数匏をシンボリック圢匏で駆動したす。 正確な小数点以䞋50桁で怜玢された数倀



 1.2502304241756868163500362795713040947699040278200
      
      





最も重芁で最適な最適化は垞にアルゎリズムレベルで行われたす:-)それにもかかわらず、行われた䜜業は圹に立たなかったわけではありたせん-結局、より耇雑なパタヌンでは分析匏を䜿甚できない可胜性が高く、すでに数倀の問題に察凊する方法がわかっおいたす。 ちなみに、合蚈の粟床が重芁な堎合は、小さな甚語を倧きな合蚈に远加するずきに有効数字が倱われないようにするために、远加の察策を講じる必芁がありたす。たずえば、Kaganアルゎリズムを䜿甚したす。 あなたが興味を持っおいたこずを願っおいたす



よろしく

アナトリヌ・アレク

シヌ゚フ05/24/2013






All Articles