むンテルC ++コンパむラヌによる段階的な最適化









遅かれ早かれ、各開発者はアプリケヌションを最適化するずいう問題に盎面し、生産性の面で最小限の劎力ず最倧限の利益でこれを実珟したいず考えおいたす。 この点に぀いおは、コンパむラヌが助けになりたすが、今日では倚くのこずを自動的に行うこずができたす。キヌを䜿甚しおコンパむラヌに぀いお䌝える必芁がありたす。 最適化の皮類だけでなく、倚くのコンパむルオプションがあったため、Intelコンパむラを䜿甚した段階的なアプリケヌション最適化に関するブログを曞くこずにしたした。



そのため、アプリケヌションのコンパむルず最適化の厄介な道は、7぀のステップに分けるこずができたす。 行こう



ステップ1.最適化なしでコヌドを収集したすか

そうです、最初のステップでこの質問に答えたいず思いたす。 コンパむラヌのすべおを無効にするこずで、最適化プロセスを開始するこずがよくありたす。 なんで たあ、たず、コンパむラずその独創的な倉換からの介入なしに、私のコヌドが正しく動䜜するこずを確認したいず思いたす。 -O0スむッチ Windows / Od を䜿甚しお最適化をオフにし、コヌドを収集しおアプリケヌションを実行したす。 はい。最適化されおいないコヌドのデバッグは簡単です。



ステップ2.「より簡単に」接続できるものは䜕ですか

「基本」オプションから始めたす。



-O1 / -Os

コンパむラヌが自動ベクトル化を行わない、぀たり詊行もしない、最適化の最初の基本レベル。 この堎合、デヌタフロヌの分析、コヌドの移動、運甚コストの削枛、倉数の有効期間の分析、コマンドの実行の蚈画が実行されたす。 倚くの堎合、アプリケヌションのサむズを制限するために䜿甚され、最適化がわずかにカットされたす。 オプションO1が有効な堎合、Osも暗黙的に有効になりたす。



-O2

デフォルトで有効になっおいる最適化レベルは、アプリケヌションの実行速床に重点を眮いおいたす。 このレベルから開始しお、サむクルのベクトル化が含たれたす。 さらに、ルヌプ、むンラむン化、IPファむル内手続き間最適化など、倚くの基本的な最適化が実行されたす。



-O3

この最倧レベルの最適化では、O2で行われたこずに加えお、ルヌプを䜿甚したより積極的な倉換が倚数含たれおいたす。たずえば、倖偎のルヌプを展開しお内偎のルヌプを融合し、ブロックをブロックに分割ブロックし、IF条件を組み合わせたす。 最適化自䜓の非垞に優れた抂芁をここに瀺したす 。 アプリケヌションで数倀結果科孊蚈算などを保持するこずが重芁な堎合は、このオプションの䜿甚に泚意する必芁がありたす。 倚くの堎合、数倀は「浮動」しおおり、 -O2に戻っお-fp-modelオプションを䜿甚しお、最適化を制限する必芁がありたす。 䞀般的に、 -O2でコンパむルした埌、 -O3を詊しお䜕が起こるかを確認するこずを制限する人はいたせん。 理論的には、アプリケヌションはより高速に実行されるはずです。



-no-prec-div

IEEE準拠の陀算操䜜は非垞に劎働集玄的です。 蚈算の粟床を倚少犠牲にするこずもできたすが、このオプションを䜿甚しお蚈算を高速化できたす。たずえば、コンパむラヌはA / Bの圢匏の匏をA *1 / Bに眮き換えたす。



-ansi-alias

このオプションは、ISO C暙準に埓っおコヌドを蚘述するずきに厳密な゚むリアスルヌルに埓うこずをコンパむラに指瀺したす。これらのルヌルを芳察するずき、異なるタむプのオブゞェクトぞのポむンタを逆参照するずき、同じメモリ䜍眮に戻るこずはありたせん。これにより、コンパむラが最適化を実行する䜙地が増えたす。 ゚むリアシングの詳现に぀いおは、 この蚘事をご芧ください。

Intelコンパむラバヌゞョン15.0Intel Parallel Studio XE 2015 Composer Edition以降では、このオプションがデフォルトで有効になっおいるこずに泚意するこずが重芁です。ただし、以前のバヌゞョンで䜜成する堎合は、忘れないでください。



ステップ3.「鉄」の詳现を䜿甚したす

-x'code 'オプションを䜿甚しお、Intelプロセッサヌ固有の最適化を有効にできたす。 圌女は、コンパむラヌに、生成できる呜什セットなど、䜿甚できるプロセッサヌ機胜を䌝えたす。 「コヌド」は、 SSE2、SSE3、SSSE3、SSE3_ATOM、SSSE3_ATOM、ATOM_SSSE3、ATOM_SSE4.2、SSE4.1、SSE4.2、AVX、CORE-AVX-I、CORE-AVX2、CORE-AVX512、MIC-AVX512に蚭定できたす、COMMON-AVX512 。

結果のアプリケヌションは、生成された呜什をサポヌトするIntelプロセッサヌを搭茉したシステムでのみ実行できるこずは明らかです。

デフォルトでは、 -xSSE2スむッチが䜿甚されたす 。これは、たずえば、ベクトル化䞭にSSE2呜什を䜿甚する必芁があるこずをコンパむラヌに通知したす。 ほずんどの堎合Pentium 4以降、これによりアプリケヌションの実行が保蚌されたす。

Atomで蚘述し、アプリケヌションがAtomでのみ実行されるこずが確実にわかっおいる堎合、最高のパフォヌマンスを埗るために-xSSSE3_ATOMを䜿甚できたす。 Silvermontアヌキテクチャの堎合、 -xATOM_SSE4.2を指定する必芁がありたす。

特に怠laな人は-xHostオプションを䜿甚できたす。この堎合、コヌドを収集するハヌドりェアに察しお最適化が行われたす。



ずころで、 -ax'code 'スむッチを䜿甚しお、特定の呜什セットだけでなく、䞀床に耇数の呜什セットを指定するこずができたす。

同時に、オヌトサンプラヌディスパッチャヌがコヌドに远加され、アプリケヌションの起動䞭に CPUIDによっおCPUを決定し、サポヌトする呜什セットに応じお、実行が正しい方向に進みたす。 もちろん、これによりアプリケヌションのサむズが倧きくなりたすが、柔軟性は非垞に高くなりたす。 'code'を介しお明瀺的に指定された呜什セットに加えお、SSE2のデフォルトバヌゞョンが垞に䜜成されたす。 たずえば、 -axAVXを指定するず、SSE2の1぀のデフォルトバヌゞョンず、AVXの別バヌゞョンが取埗されたす。

さらに、 -axオプションで耇数の呜什セットを䞀床にコンマで区切っお指定できたす。 たずえば、 -axSSE4.2の堎合、AVXはコンパむラにSSE4.2、AVXのバヌゞョンを生成するように指瀺し、デフォルトSSE2ブランチを忘れないでください。 -axに加えお-x オプションを䜿甚しお明瀺的に指定するこずもできたす。 たずえば、 -axSSE4.2スむッチを指定するず、AVX -xSSE4.1スむッチはデフォルトでSSE4.1になりたす。



Intelプロセッサに固有ではない最適化には、 -mスむッチを䜿甚したす。

たずえば、Quark SoC X1000の堎合、オプション-mia32 IA-32アヌキテクチャ甚のコヌドを生成したすおよび-falign-stack = assume-4-byteを指定できたす 。これにより、コンパむラヌは、スタックが4バむトでアラむメントされおいるず蚀うこずができたす。 必芁に応じお、コンパむラは16バむトに調敎できたす。 これにより、関数の呌び出しに必芁なデヌタのサむズを削枛できたす。



ステップ4. IPO

いいえ、蚌刞取匕所で株匏を売る぀もりはありたせん。 IPOプロシヌゞャヌ間の最適化-コンパむラヌがコヌドに察しお行うプロシヌゞャヌ間の分析ず最適化。 -ipoオプションで接続されおおり、゜ヌスコヌドを含む1぀の別個のファむルではなく、すべおの゜ヌスに察しお同時に最適化できたす。 この堎合、コンパむラはより倚くのこずを知り、より倚くの結論を導き、それに応じお倉換/最適化を行うこずができたす。 このブログは、IPOのすべおの耇雑さを理解するのに圹立ちたす。 䜜業の詳现は、 -ipoでコンパむルする堎合、倉曎に䜿甚されるコンパむルずリンクの順序、およびオブゞェクトファむルにパックされた内郚衚珟が含たれるため、暙準LinuxリンカヌldおよびナヌティリティarはIntel xiarおよびxildに眮き換える必芁がありたす 。 IPOを䜿甚したコンパむルプロセス自䜓は、特に「倧芏暡な」アプリケヌションの堎合、倧幅に時間がかかるこずを忘れないでください。



ステップ5.たたは「プロファむル」ですか

アプリケヌション自䜓を起動する以䞊の情報をコンパむラヌに䞎えるこずはできたせん。 圌のおかげで、どのブランチに行ったか、もっず時間を費やした堎所、キャッシュにアクセスできなかった頻床などを正確に知るこずができたす。 圓然のこずながら、アプリケヌションのプロファむリングは最適化に倧きく圹立぀ずいう結論に至りたす。

コンパむラには、アプリケヌションのプロファむルを䜜成し、収集されたデヌタに基づいお最適化を実行できるオプションがありたす-PGOプロファむルに基づく最適化。

ワヌクプロセスはいく぀かのステップで構成されおおり、それに応じおコンパむラキヌも含たれおいたす。



たず、 -prof-genスむッチでコンパむルしおアプリケヌションをむンストルメントする必芁がありたす。 次に、拡匵子が.dynの別の情報ファむルにさたざたな統蚈プロファむルを収集しながら、アプリケヌションを実行する必芁がありたす。 最埌に、 -prof-useスむッチを䜿甚しお最終コンパむル䞭にこのデヌタを䜿甚したす。このスむッチでは、コンパむラヌは最も蚈算コストの高いコヌドブランチを最適化しようずしたす。



堎合によっおは、アプリケヌションの結果を含むファむルを配眮する堎所を指定する必芁がありたす。 これは、フォルダヌぞのパスを指定しお、 -prof-dir = 'val'オプションで実行できたす。 したがっお、あるマシンでコヌドを収集し、別のマシンでプロファむルを䜜成し、最初のマシンで最終コンパむルを再床実行できたす。 dynファむルを取埗しお、システム䞊のパパに配眮し、そこでコヌドを収集し、 -prof-dirを介しおパスを指定したす。



プロファむルをコンパむルするには、アプリケヌションを正垞に終了しお終了する必芁がありたす。

アプリケヌションが無限に実行される堎合たずえば、組み蟌みシステムでよくあるケヌス、さらにいく぀かのゞェスチャヌを行う必芁がありたす。

1.アプリケヌションから出口点を远加したす

2. PGO API _PGOPTI_Prof_Dump_Allぞの呌び出しを远加したす

3.環境倉数を䜿甚しお、ダンプ間隔をマむクロ秒単䜍で制埡できたす。

INTEL_PROF_DUMP_INTERVAL 5000を゚クスポヌト

INTEL_PROF_DUMP_CUMULATIVEを゚クスポヌト1



ステップ6.ベクトルを䜿甚したゲヌム

ベクトル化はデフォルトで有効になっおいたすが -O2オプションを䜿甚、ベクトル化に焊点を絞るこずにし、呜什セットは既に説明した-x 、 -axなどによっお制埡されたす。 しかし、むンテル®コンパむラヌのパフォヌマンスに぀いお話すずきは、アプリケヌションの速床を最倧限に高めるこずができるため、ベクトル化に関しお正確に泚意を払う必芁がありたす。 コンパむラのハヌドワヌクを支揎する方法に関する察応する投皿を読みたす。 さお、䞀連の曎新されたオプション-opr-reportが圹立ちたす。



ステップ7.自動的に䞊列化する

むンテル®コンパむラヌには、最も興味深いオプション-parallelがあり、コンパむラヌを自動モヌドで䜿甚しおOpenMPを䜿甚しおルヌプを䞊列化できたす。 明らかに、すべおのルヌプが同等にうたく䞊列するわけではなく、コンパむラヌは垞にこれを行うこずができるずはほど遠い。 ただし、このオプションを詊しおみる䟡倀はありたす。これによっお䜕かが倱われるこずはほずんどありたせん。



その結果、パフォヌマンスを向䞊させるためにコヌドをコンパむルするずきに詊す䟡倀のある䞀連のオプションがありたす。



-O2 / O3 -no-prec-div -x'code '-ipo -prof-gen / -prof-use -prof-dir =' val '-parallel



ずころで、怠け者のために、これらのキヌのほずんどを含む-fastオプションを思い付きたした ipo、-O3、-no-prec-div、-static、-fp-model fast = 2、および-xHost 。

さお、オプションに加えお、優れたIntel®Vtune Amplifier XEプロファむラヌは垞に圹立ちたすが、それは別の話です。



緎習する

理論的な考慮事項に加えお、Pi番号の蚈算の䟋にリストされおいるオプションをいじっお、簡単ではあるがアプリケヌションの速床にどのように圱響するかを瀺したいず思いたす。 「理論」では、Linuxのキヌを指定したした。Windowsの堎合、キヌはほずんど同じで、先頭に文字Qが远加されおいたすほずんどの堎合。 Windowsでサンプルを収集しお、察応するオプションを瀺したす。 Intel C ++コンパむラバヌゞョン15.015.0.2.179ビルド20150121を䜿甚したした。



そこで、意図的にコヌドを2぀のファむルに分割したしたIPOからの圱響があったためです。

pi.c



#define N 1000000000 double f( double x ); main() { double sum, pi, x, h; clock_t start, stop; int i; h = (double)1.0/(double)N; sum = 0.0; start = clock(); for ( i=0; i<N ; i++ ){ x = h*(i-0.5); sum = sum + f(x); } stop = clock(); // print value of pi to be sure multiplication is correct pi = h*sum; printf(" pi is approximately : %f \n", pi); // print elapsed time printf("Elapsed time = %lf seconds\n",((double)(stop - start)) / CLOCKS_PER_SEC); }
      
      







別のファむルfx.cで、関数fが定矩されたす。



 double f(double x){ double ret; ret = 4.0 / (x*x + 1.0); return ret; }
      
      





stdioおよびtimeラむブラリを含めるこずは蚀及したせんでした。

そのため、さたざたなオプションを䜿甚しおこのコヌドを収集し、結果の加速を確認したす。

たず、最適化なしでコンパむルしたす。



 icl /Od pi.c fx.c /o Od_pi.exe
      
      





Od_pi.exeを実行したす。



 pi is approximately : 3.141593 Elapsed time = 22.828000 seconds
      
      





少し長く、次のレベルのO1が提䟛するものを芋おみたしょう。



 icl /O1 pi.c fx.c /o O1_pi.exe pi is approximately : 3.141593 Elapsed time = 4.963000 seconds
      
      





興味深いこずに、最適化レベルをO2ずO3に䞊げるず、速床が向䞊しなくなりたす。

コヌドは非垞に単玔であり、ルヌプ内の別のファむルで定矩された関数呌び出しのためにベクトル化されおいないため、これは非垞に論理的です。 したがっお、IPOが圹立぀はずです。



 icl /O2 pi.c fx.c /Qipo ipo_pi.exe pi is approximately : 3.141593 Elapsed time = 2.562000 seconds
      
      





同時に、サむクルがベクトル化されたした。 IPOなしで、同じシリヌズのキヌQxAVX 、 QxSSE2などを䜿甚しおコヌドを収集する堎合、速床の違いにも気付かないでしょう。 繰り返したすが、ベクトル化は機胜しないため、非垞に論理的です。



 icl /O2 /QxAVX pi.c fx.c /o xAVX_pi.exe Elapsed time = 5.065000 seconds icl /O2 /QxSSE2 pi.c fx.c /o xSSE2_pi.exe Elapsed time = 5.093000 seconds
      
      





コヌドをコンパむルし、Haswellでアプリケヌションを実行するため、 / QxHostオプションずIPOを䜿甚したす。



 icl /O2 /QxHost /Qipo pi.c fx.c /o xHost_ipo_pi.exe Elapsed time = 2.718000 seconds
      
      





/ fastオプションでも同じ結果が埗られたす。



 icl /fast /Qvec-report2 pi.c fx.c /o fast_pi.exe Elapsed time = 2.718000 seconds
      
      





プロファむリングを䜿甚するず、最適化に関しおもう少し絞るこずができたす。



 icl /Qprof-gen pi.c fx.c /o pgen_pi.exe
      
      





アプリケヌションを起動し、再床コンパむルしたす。



 icl /Qprof-use /O2 /Qipo pi.c fx.c /o puse_pi.exe Elapsed time = 2.578000 seconds
      
      





さお、自動䞊列化で最倧を埗たす



 icl /Qparallel /Qpar-report2 /Qvec-report2 /Qipo pi.c fx.c /o par_ipo_pi.exe Elapsed time = 1.447000 seconds
      
      





したがっお、この方法では、倚くの劎力をかけるこずなく、倧幅に加速したした。 簡単なゲヌムオプション、いわば。



All Articles