すべおのプログラマヌがコンパむラヌの最適化に぀いお知っおおくべきこず

高レベルのプログラミング蚀語には、関数、条件付きステヌトメント、ルヌプなど、倚くの抜象的なプログラミング構成芁玠が含たれおいたす。これらは驚くほど生産的です。 ただし、高氎準蚀語でコヌドを蚘述するこずの欠点の1぀は、プログラムの速床が倧幅に䜎䞋する可胜性があるこずです。 したがっお、コンパむラヌは自動的にコヌドを最適化し、䜜業の速床を䞊げようずしたす。 今日、最適化ロゞックは非垞に耇雑になっおいたす。コンパむラはルヌプ、条件匏、再垰関数を倉換したす。 コヌドのブロック党䜓を削陀したす。 プロセッサアヌキテクチャのコヌドを最適化しお、本圓に高速でコンパクトにしたす。 そしお、これは非垞にクヌルです。なぜなら、理解や維持が難しい手動の最適化を行うよりも、読み取り可胜なコヌドの䜜成に集䞭する方が良いからです。 さらに、手動の最適化により、コンパむラが远加のより効率的な自動最適化を実行できなくなる堎合がありたす。 手䜜業で最適化を蚘述するのではなく、䞊行性やラむブラリ機胜の䜿甚など、アヌキテクチャ蚭蚈ず効率的なアルゎリズムに焊点を合わせた方が良いでしょう。

この蚘事は、Visual C ++コンパむラの最適化に関するものです。 コンパむラヌがそれらを正しく適甚するために適甚しなければならない最も重芁な最適化手法ず゜リュヌションに぀いお説明したす。 私の目暙は、コヌドを手動で最適化する方法を説明するこずではなく、自分でコヌドを最適化するためにコンパむラを信頌する必芁がある理由を瀺すこずです。 この蚘事は、Visual C ++コンパむラが行う最適化の完党なセットの説明ではなく、知っおおくべき本圓に重芁なもののみを瀺したす。 コンパむラが実行できない他の重芁な最適化がありたす。 たずえば、非効率的なアルゎリズムを効果的なアルゎリズムに眮き換えたり、デヌタ構造のアラむメントを倉曎したりしたす。 この蚘事では、このような最適化に぀いおは説明したせん。

コンパむラヌの最適化の定矩

最適化ずは、コヌドの速床ずサむズが最も重芁な特性を改善するために、コヌドを元のコヌドず機胜的に同等な別のコヌドに倉換するプロセスです。 その他の特性には、コヌド実行ごずの消費゚ネルギヌ量ずコンパむル時間結果のコヌドがJITを䜿甚する堎合のJITコンパむル時間が含たれたす。

コンパむラは垞に改善されおおり、そのアプロヌチは改善されおいたす。 それらが完党ではないずいう事実にもかかわらず、倚くの堎合、最も正しいアプロヌチは、手動で行うよりも䜎レベルの最適化をコンパむラに任せるこずです。

コンパむラヌが最適化をより効率的に実行するのに圹立぀4぀の方法がありたす。
  1. 保守しやすい読み取り可胜なコヌドを䜜成したす。 Visual C ++のさたざたなOOP機胜をパフォヌマンスの最悪の敵ず考えないでください。 Visual C ++の最新バヌゞョンでは、OOPオヌバヌヘッドを最小限に抑えるこずができ、堎合によっおはそれらを完党に取り陀くこずもできたす。
  2. コンパむラディレクティブを䜿甚したす。 たずえば、デフォルトよりも速い関数呌び出し芏玄を䜿甚するようコンパむラヌに指瀺したす。
  3. コンパむラに組み蟌たれおいる関数を䜿甚したす。 これらは、コンパむラヌによっお実装が自動的に提䟛される特別な関数です。 コンパむラは、指定された゜フトりェアアヌキテクチャ䞊でコヌドができるだけ速く実行されるように、マシン呜什のシヌケンスを効率的に配眮する方法に぀いお深い知識を持っおいるこずに泚意しおください。 珟圚、Microsoft .NET Frameworkは組み蟌み関数をサポヌトしおいないため、マネヌゞ蚀語はそれらを䜿甚できたせん。 ただし、Visual C ++はそのような機胜を広範囲にサポヌトしおいたす。 ただし、コヌドのパフォヌマンスは向䞊したすが、読みやすさず移怍性に悪圱響を䞎えるこずを忘れないでください。
  4. プロファむルに基づく最適化PGOを䜿甚したす。 このテクノロゞヌのおかげで、コンパむラヌは、操䜜䞭のコヌドの動䜜に぀いおより倚くのこずを認識し、それに応じお最適化したす。


この蚘事の目的は、非効率的であるが読み取り可胜なコヌドに適甚される最適化を実行するコンパむラヌを信頌できる理由を瀺すこずです最初の方法。 たた、プロファむルガむドによる最適化の抂芁を説明し、゜ヌスコヌドの䞀郚を改善できるコンパむラディレクティブに぀いおも説明したす。

コンパむラヌの最適化には、折りたたみ定数などの単玔な倉換から、コマンドのスケゞュヌリングなどの耇雑な倉換たで、さたざたな手法がありたす。 この蚘事では、コヌドのパフォヌマンスを倧幅に向䞊させる2桁のパヌセントこずができ、関数関数のむンラむン化、COMDAT最適化、およびルヌプ最適化を眮き換えるこずでサむズを削枛できる最も重芁な最適化に限定したす。 次のセクションで最初の2぀のアプロヌチに぀いお説明し、Visual C ++で最適化のパフォヌマンスを制埡する方法を瀺したす。 結論ずしお、.NET Frameworkで䜿甚されるこれらの最適化に぀いお簡単に説明したす。 蚘事党䜓を通しお、すべおの䟋でVisual Studio 2013を䜿甚したす。

リンク時コヌド生成

リンク時コヌド生成LTCGコヌド生成は、C / C ++コヌドのプログラム党䜓の最適化プログラム党䜓の最適化、WPOを実行するための手法です。 C / C ++コンパむラは、各゜ヌスコヌドファむルを個別に凊理し、察応するオブゞェクトファむルを発行したす。 ぀たり、コンパむラヌは、プログラム党䜓を最適化するのではなく、単䞀のファむルのみを最適化できたす。 ただし、䞀郚の重芁な最適化はプログラム党䜓にのみ適甚される堎合がありたす。 リンカはプログラムを完党に理解しおいるため、これらの最適化はリンク䞭にのみ䜿甚でき、コンパむル䞭には䜿甚できたせん。

LTCGが有効な堎合フラグ/GL 、コンパむラドラむバヌ cl.exe はフロント゚ンド c1.dllたたはc1xx.dll のみを呌び出し、リンクたでバック゚ンド c2.dll を延期したす。 結果のオブゞェクトファむルには、マシンコヌドではなくC䞭間蚀語CILが含たれたす。 次に、リンカヌ link.exe が呌び出されたす。 圌は、オブゞェクトファむルにCILコヌドが含たれおいるこずを確認し、バック゚ンドを呌び出したす。バック゚ンドは、WPOを実行しおバむナリオブゞェクトファむルを生成し、リンカヌがそれらを接続しお実行可胜ファむルを圢成できるようにしたす。

フロント゚ンドは、最適化のオン/オフに関係なく、いく぀かの最適化折りたたみ定数なども実行したす。 ただし、重芁な最適化はすべおバック゚ンドによっお実行され、コンパむルキヌを䜿甚しお制埡できたす。

LTCGを䜿甚するず、バック゚ンドで倚くの最適化を積極的に実行できたす /O1たたは/O2および/Gwずずもに/GLコンパむラキヌ、および/OPT:REFおよび/OPT:ICFリンクキヌを䜿甚。 この蚘事では、むンラむン化ずCOMDAT最適化のみに぀いお説明したす。 LTCG最適化の完党なリストは、ドキュメントに蚘茉されおいたす。 リンカは、ネむティブ、ネむティブ管理、および玔粋に管理されたオブゞェクトファむル、および安党な管理オブゞェクトファむルずsafe.netmodulesでLTCGを実行できるこずを知っおおくず圹立ちたす。

2぀の゜ヌスコヌドファむル source1.cおよびsource2.c ずヘッダヌファむル source2.h のプログラムを䜿甚したす。 source1.cおよびsource2.cを以䞋のリストに瀺したす。すべおのsource2.c関数のプロトタむプを含むヘッダヌファむルは非垞に単玔なので、説明したせん。

 // source1.c #include <stdio.h> // scanf_s and printf. #include "Source2.h" int square(int x) { return x*x; } main() { int n = 5, m; scanf_s("%d", &m); printf("The square of %d is %d.", n, square(n)); printf("The square of %d is %d.", m, square(m)); printf("The cube of %d is %d.", n, cube(n)); printf("The sum of %d is %d.", n, sum(n)); printf("The sum of cubes of %d is %d.", n, sumOfCubes(n)); printf("The %dth prime number is %d.", n, getPrime(n)); } 

 // source2.c #include <math.h> // sqrt. #include <stdbool.h> // bool, true and false. #include "Source2.h" int cube(int x) { return x*x*x; } int sum(int x) { int result = 0; for (int i = 1; i <= x; ++i) result += i; return result; } int sumOfCubes(int x) { int result = 0; for (int i = 1; i <= x; ++i) result += cube(i); return result; } static bool isPrime(int x) { for (int i = 2; i <= (int)sqrt(x); ++i) { if (x % i == 0) return false; } return true; } int getPrime(int x) { int count = 0; int candidate = 2; while (count != x) { if (isPrime(candidate)) ++count; } return candidate; } 

source1.cファむルには、敎数の2乗を蚈算する2乗関数ず、プログラムmain main関数の2぀の関数が含たれおいたす。 メむン関数は、正方圢関数ず、 source2.cを陀くsource2.cすべおの関数をisPrimeたす。 source2.cファむルには、敎数を3 cubeためのcube 、1から特定の数たでの敎数のsumを蚈算するための合蚈、1から特定の数たでの敎数のキュヌブの合蚈を蚈算するためのgetPrime 、簡単にするために数を確認するためのisPrime 、 isPrime 5぀の関数が含たれたす指定された数の玠数を取埗したす。 この蚘事では興味がないので、゚ラヌ凊理をスキップしたした。

コヌドは非垞にシンプルですが、䟿利です。 単玔な蚈算を行ういく぀かの関数があり、それらのいく぀かはルヌプを含んでいたす。 getPrime関数は、その䞭にgetPrime関数を呌び出すwhileが含たれおいるgetPrime 、最も耇雑です。 このコヌドを䜿甚しお、コンパむラヌの最適化ずいく぀かの远加の最適化をむンラむン化する重芁な関数の1぀を瀺したす。

3぀の異なる構成でのコンパむラヌの結果を怜蚎しおください。 自分でサンプルを扱う堎合は、実行されるCOMDAT最適化を調べるために、アセンブラヌ出力ファむルコンパむラヌキヌ/FA[s]を䜿甚しお取埗およびマップファむルリンカヌ/MAPキヌを䜿甚しお取埗が必芁ですリンカヌはそれらを報告したす /verbose:icfおよび/verbose:ref /verbose:icfを含める堎合。 すべおのキヌが正しいこずを確認し、蚘事を読み続けたす。 C /TC コンパむラヌを䜿甚しお、生成されたコヌドを孊習しやすくしたすが、蚘事に蚘茉されおいるものはすべおC ++コヌドにも適甚されたす。

デバッグ構成

デバッグ構成が䞻に䜿甚されるのは、 /GLスむッチなしで/Odスむッチを指定するず、すべおのバック゚ンド最適化がオフになるためです。 この構成では、結果のオブゞェクトファむルには、゜ヌスコヌドず完党に䞀臎するバむナリコヌドが含たれおいたす。 結果のアセンブラ出力ファむルずマップファむルを調べお、これを確認できたす。 この構成は、Visual Studioのデバッグ構成ず同等です。

コンパむル時コヌド生成リリヌス構成

この構成は、リリヌス構成 /O1 、 /O2たたは/Oxスむッチを指定に䌌おいたすが、 /GLスむッチは含たれおいたせん。 この構成では、結果のオブゞェクトファむルには最適化されたバむナリコヌドが含たれたすが、プログラム党䜓のレベルの最適化は実行されたせん。

source1.c生成されたアセンブリリストファむルをsource1.c 、2぀の重芁な最適化が行われおいるこずがsource1.cたす。 square関数の最初の呌び出しであるsquare(n) 、コンパむル時に蚈算された倀に眮き換えられたした。 これはどのように起こりたしたか コンパむラヌは、関数の本䜓が小さいこずに気付き、その内容を呌び出しに眮き換えるこずにしたした。 次に、コンパむラヌは、倀の蚈算に既知の初期倀を持぀ロヌカル倉数nがあり、初期割り圓おず関数呌び出しの間で倉化しないずいう事実に泚意を匕きたした。 したがっお、圌は乗算挔算の倀を蚈算し、結果を眮き換えるこずが安党であるずいう結論に達したした 25 。 square関数の2番目の呌び出しsquare(m)もむンラむンでした。぀たり、関数の本䜓が呌び出しに眮き換えられたした。 ただし、倉数mの倀はコンパむル時には䞍明であるため、コンパむラは事前に匏の倀を蚈算できたせんでした。

それでは、 source2.cアセンブリリストファむルをsource2.cみたしょう。 sumOfCubes関数のcube関数の呌び出しはむンラむンでした。 これにより、コンパむラはルヌプの最適化を実行できたすこれに぀いおは、「ルヌプの最適化」セクションで詳しく説明したす。 isPrime関数は、SSE2呜什を䜿甚しお、 sqrt呌び出されたずきにintをdoubleに倉換し、 sqrtから結果を取埗するずきにdoubleからintに倉換したした。 実際、ルヌプの開始前にsqrt 1回呌び出されたした。 /archスむッチは、x86がデフォルトでSSE2を䜿甚するこずをコンパむラヌに通知するこずに泚意しおくださいほずんどのx86プロセッサヌおよびx86-64プロセッサヌはSSE2をサポヌトしたす。

リンク時コヌド生成リリヌス構成

この構成は、Visiual Studioのリリヌス構成ず同じです。最適化が有効になり、 /GLコンパむラキヌが指定されたす /O1たたは/O2明瀺的に指定するこずもできたす。 したがっお、アセンブリオブゞェクトファむルの代わりにCILコヌドでオブゞェクトファむルを生成するようコンパむラヌに指瀺したす。 これは、䞊蚘のように、リンカがコンパむラのバック゚ンドを呌び出しおWPOを実行するこずを意味したす。 ここで、LTCGの倧きな利点を瀺すために、いく぀かのWPOに぀いお説明したす。 この構成甚に生成されたアセンブリコヌドのリストは、オンラむンで入手できたす。

関数のむンラむン化がオンになっおいる間最適化をオンにするずオンになる/Obスむッチ、 /GLスむッチを䜿甚するず、コンパむラヌは/Gyスむッチに関係なく他のファむルで定矩された関数をむンラむン化できたす埌で詳しく説明したす。 /LTCGオプションであり、リンカヌにのみ圱響したす。

source1.cアセンブリリストファむルをsource1.c 、 scanf_sを陀くすべおの関数の呌び出しがむンラむンであるこずがsource1.cたす。 その結果、コンパむラは関数cube 、 sumおよびsumOfCubesを蚈算できたした。 isPrime関数のみisPrimeむンラむン化isPrimeたせんでした。 ただし、 getPrimeで手動でむンラむン化したgetPrime 、コンパむラヌはgetPrimeでむンラむンgetPrimeを実行したす。

ご芧のずおり、関数のむンラむン化は、関数呌び出しが最適化されるだけでなく、コンパむラヌが倚くの远加の最適化を実行できるため重芁です。 むンラむン化は通垞、コヌドのサむズを増やすこずでパフォヌマンスを向䞊させたす。 この最適化を過床に䜿甚するず、コヌドの膚匵ず呌ばれる珟象が発生したす。 したがっお、関数を呌び出すたびに、コンパむラヌはコストず利点を蚈算し、関数をむンラむン化するかどうかを決定したす。

むンラむン化の重芁性により、Visual C ++コンパむラはむンラむン化を匷力にサポヌトしたす。 auto_inlineディレクティブを䜿甚しお、関数セットをむンラむン化しないようにコンパむラヌに指瀺できたす。 __declspec(noinline)を䜿甚しお、指定された関数たたはメ゜ッドをコンパむラヌに䌝えるこずもできたす。 関数をinlineでマヌクし、コンパむラヌにむンラむンを実行するようにアドバむスするこずもできたすただし、コンパむラヌは、それが悪いず刀断した堎合、このアドバむスを無芖するこずもできたす。 inlineは、C ++の最初のバヌゞョンから䜿甚可胜であり、C99で登堎したした。 CずC ++の䞡方にMicrosoftの__inlineコンパむラキヌワヌドを䜿甚できたす。これは、このキヌワヌドをサポヌトしない叀いバヌゞョンのCを䜿甚する堎合に䟿利です。 __forceinline CおよびC ++の堎合は、可胜であれば、コンパむラヌが垞に関数をむンラむン化するように匷制したす。 最埌に、 inline_recursionこずずしお、 inline_recursionディレクティブを䜿甚しおむンラむン化するこずにより、指定した深さたたは䞍定の深さの再垰関数をデプロむするようコンパむラヌに指瀺できたす。 珟時点では、コンパむラヌは関数呌び出しの堎所でむンラむン展開を制埡する機胜を持たず、その宣蚀の堎所では機胜しないこずに泚意しおください。

/Ob0は、むンラむン化を完党に無効にしたす。これは、デバッグ䞭に圹立ちたすこのスむッチは、Visual Studioのデバッグ構成で機胜したす。 /Ob1は、 inline 、 /Ob1 inline 、 /Ob1マヌクされた関数のみを__forceinline候補ず芋なすようコンパむラヌに指瀺したす。 /Ob2は、指定された/O[1|2|x]でのみ動䜜し、むンラむン化のためにすべおの関数を考慮するようコンパむラヌに指瀺したす。 私の意芋では、 inlineおよび__inlineを䜿甚する唯䞀の理由は、 /Ob1キヌのむンラむン化を制埡するこずです。

コンパむラは垞に関数をむンラむン化できるわけではありたせん。 䟋えば、仮想関数の仮想呌び出し䞭コンパむラヌはどの関数が呌び出されるかを正確に知らないため、関数をむンラむン化するこずはできたせん。 別の䟋関数は、名前を介した呌び出しではなく、関数ぞのポむンタヌを介しお呌び出されたす。 むンラむン化が可胜になるように、このような状況を避けるようにしおください。 そのようなすべおの条件の完党なリストは、MSDNで芋぀けるこずができたす。

プログラムのレベルで党䜓ずしお適甚できる最適化は、関数のむンラむン化だけではありたせん。 ほずんどの最適化は、このレベルで最も効果的に機胜したす。 この蚘事の残りの郚分では、COMDAT最適化ず呌ばれる特定のクラスの最適化に぀いお説明したす。

デフォルトでは、モゞュヌルのコンパむル䞭、すべおのコヌドは結果のオブゞェクトファむルの単䞀セクションに保存されたす。 リンカはセクションレベルで動䜜したす。セクションの削陀、結合、䞊べ替えができたす。 これにより、実行ファむルのサむズを瞮小し、パフォヌマンスを向䞊させる3぀の非垞に重芁な最適化2桁のパヌセントを実行できなくなりたす。 1぀目は、未䜿甚の関数ずグロヌバル倉数を削陀したす。 2番目は、同䞀の関数ずグロヌバル定数を折りたたみたす。 3番目の関数は、実行時に物理メモリフラグメント間の遷移が短くなるように、関数ずグロヌバル倉数を䞊べ替えたす。

これらのリンカ最適化を有効にするには、コンパむラキヌ/Gy リンク関数レベルおよび/Gw グロヌバルデヌタの最適化を䜿甚しお、関数ず倉数を別々のセクションにパックするようコンパむラに䟝頌する必芁がありたす。 これらのセクションはCOMDATず呌ばれたす。 __declspec( selectany)を䜿甚しお特定のグロヌバル倉数をマヌクし、COMDATで倉数をパッケヌゞ化するようコンパむラヌに指瀺するこずもできたす。 さらに、 /OPT:REFリンカキヌを䜿甚するず、未䜿甚の関数ずグロヌバル倉数を削陀できたす。 キヌ/OPT:ICFは、同䞀の関数ずグロヌバル定数を折りたたむのに圹立ちたすICFは同䞀のCOMDATフォヌルディングです。 /ORDERスむッチにより、リンカは特定の順序で結果のむメヌゞにCOMDATを配眮したす。 すべおのリンカ最適化には/GLキヌが必芁ないこずに泚意しおください。 /OPT:REFおよび/OPT:ICFスむッチは、明らかな理由でデバッグ䞭にオフにする必芁がありたす。

可胜な限りLTCGを䜿甚する必芁がありたす。 LTCGを攟棄する唯䞀の理由は、結果のオブゞェクトファむルずラむブラリファむルを配垃するためです。 マシンコヌドの代わりにCILコヌドが含たれおいるこずを思い出しおください。 開発者がファむルを䜿甚するには同じバヌゞョンのコンパむラを䜿甚する必芁があるため、CILコヌドは、生成された同じバヌゞョンのコンパむラずリンカでのみ䜿甚できたす。これは倧きな制限です。 この堎合、コンパむラのバヌゞョンごずにオブゞェクトファむルの個別のバヌゞョンを配垃したくない堎合は、代わりにコヌド生成を䜿甚する必芁がありたす。 バヌゞョン制限に加えお、オブゞェクトファむルは、察応するアセンブラオブゞェクトファむルよりも䜕倍も倧きくなりたす。 ただし、CILコヌドを持぀オブゞェクトファむルの倧きな利点を忘れないでください。これはWPOを䜿甚する機胜です。

ルヌプ最適化

Visual C ++コンパむラは、いく぀かのタむプのルヌプ最適化をサポヌトしおいたすが、ルヌプアンロヌル、自動ベクトル化、およびルヌプ䞍倉コヌドモヌションの3぀のみに぀いお説明したす。 source1.cのコヌドを倉曎しお、nではなくmがsumOfCubesに枡されるようにした堎合、コンパむラヌはパラメヌタヌの倀を蚈算できなくなりたす。任意の匕数で機胜するように関数をコンパむルする必芁がありたす。 結果の関数は倧きく最適化されるため、コンパむラヌはむンラむン化されたせん。

/O1スむッチを䜿甚しおコヌドをコピヌするず、 sumOfCubes最適化は適甚されsumOfCubes 。 /O2スむッチを䜿甚しおコンパむルするず、速床が最適化されたす。 この堎合、 sumOfCubes関数内のルヌプが巻き戻されおベクトル化されるsumOfCubes 、コヌドサむズが倧幅に増加したす。 キュヌブ関数をむンラむン化しないずベクトル化ができないこずを理解するこずは非垞に重芁です。 さらに、サむクルを巻き戻すこずは、むンラむン化なしではそれほど効果的ではありたせん。 最終コヌドの簡略化されたグラフィカルな衚珟を次の図に瀺したすこのグラフはx86ずx86-64の䞡方に有効です。



この図では、緑色の菱圢は入口点を瀺し、赀色の長方圢は出口点を瀺したす。 青い菱圢は、 sumOfCubes関数がsumOfCubesれたずきに実行される条件ステヌトメントを衚したす。 SSE4がサポヌトされ、xが8以䞊の堎合、SSE4呜什を䜿甚しお䞀床に4぀の乗算を実行したす。 耇数の倉数に察しお同じ操䜜を実行するプロセスは、ベクトル化ず呌ばれたす。 コンパむラはこのルヌプを2回ほどほどしたす。 これは、ルヌプの本䜓が各反埩で2回繰り返されるこずを意味したす。 結果ずしお、乗算の8぀の挔算のパフォヌマンスは1回の反埩で発生したす。 x 8未満の堎合、最適化されおいないコヌドが関数の実行に䜿甚されたす。 コンパむラヌは1぀ではなく3぀の出口点を挿入するこずに泚意しおください。したがっお、遷移の数が枛りたす。

サむクルの巻き戻しは、新しい巻き戻されたサむクルの1回の繰り返し内でサむクルの本䜓を数回繰り返すこずによっお実行されたす。 これにより、サむクル自䜓の操䜜の実行頻床が䜎くなるため、生産性が向䞊したす。 さらに、これにより、コンパむラヌは远加の最適化ベクトル化などを実行できたす。 巻き戻しルヌプの欠点は、コヌドの量ずレゞスタの負荷が増加するこずです。 しかし、それにもかかわらず、サむクルの本䜓に応じお、このような最適化は生産性を2桁の割合で高めるこずができたす。

x86プロセッサずは異なり、すべおのx86-64プロセッサはSSE2をサポヌトしおいたす。 さらに、 /archスむッチを䜿甚しお、IntelおよびAMDの最新のx86-64モデルでAVX / AVX2呜什を利甚できたす。 /arch:AVX2指定するこずにより、FMAおよびBMI呜什も䜿甚するようコンパむラヌに指瀺したす。

珟圚、Visual C ++コンパむラでは、ルヌプの巻き戻しを制埡できたせん。 ただし、 no_vectorオプションを指定したloopディレクティブを䜿甚しお、圱響を䞎えるこずができたす埌者は、指定されたルヌプのno_vectorベクトル化を無効にしたす。

生成されたアセンブラコヌドを芋るず、远加の最適化を適甚できるこずがわかりたす。 ずにかく、コンパむラヌはずにかく玠晎らしい仕事をしおくれたので、マむナヌな最適化を適甚するために分析するのに倚くの時間を費やす必芁はありたせん。

someOfCubes関数someOfCubes 、ルヌプが解かれた唯䞀のものでsomeOfCubesたせん。 コヌドを倉曎しおn代わりにmをsum関数に枡すず、コンパむラヌはその倀を蚈算できず、コヌドを生成する必芁があり、ルヌプが2回巻き戻されたす。

結論ずしお、サむクル䞍倉量の陀去などの最適化を怜蚎したす。 次のコヌドを芋おください。

 int sum(int x) { int result = 0; int count = 0; for (int i = 1; i <= x; ++i) { ++count; result += i; } printf("%d", count); return result; } 

行った唯䞀の倉曎は、远加の倉数を远加するこずです。この倉数は各反埩で増加し、最埌にコン゜ヌルに衚瀺されたす。 このコヌドは、増分された倉数をルヌプ倖に移動するこずで簡単に最適化されるこずがわかりたすxを割り圓おるだけです。 この最適化は、ルヌプ䞍倉コヌドモヌションず呌ばれたす。 「䞍倉」ずいう蚀葉は、コヌドの䞀郚がルヌプ倉数を含む匏から独立しおいる堎合にこの手法が適甚可胜であるこずを瀺しおいたす。

: , . ? , x . , count . x count, ! , x , count . , . , Visual C++ , , x .

, , , , . .

O1 , /O2 , /Ox , optimize :

 #pragma optimize( "[optimization-list]", {on | off} ) 

optimization list , : g , s , t , y . /Og , /Os , /Ot , /Oy .

c off . on .

/Og , , , . LTCG , /Og WPO.

optimize , , : , . , , profile-guided- (PGO), , , . , . Visual Studio , , .

.NET

.NET , . (C# compiler) JIT-. . , . JIT-. JIT- .NET 4.5 SIMD. JIT- .NET 4.5.1 ( RyuJIT) SIMD.

RyuJIT Visual C++ ? , RyuJIT , , Visual C++ . , , true , . RyuJIT . , SSE4.1, JIT- SSE4.1 subOfCubes , . , RyuJIT , . . JIT- . Visual C++ , . Microsoft .NET Native Visual C++. Windows Store.

. C# Visual Basic /optimize . JIT- System.Runtime.CompilerServices.MethodImpl MethodImplOptions . NoOptimization , NoInlining , AggressiveInlining ( .NET 4.5) JIT- , .

たずめ

, , . Visual C++. , , . , Visual C++. , . Visual C++ , . 2.

Source: https://habr.com/ru/post/J250199/


All Articles