先週、Intelは新しいバージョンのC / C ++コンパイラをリリースしました-16.0、別名Parallel Studio XE Composer Edition for C ++。 新しい標準(C11、C ++ 14、OpenMP 4.1)のサポート、Xeon Phiでの作業の可能性、ライブラリの新しいバージョンのリリース、および「おいしい」が大幅に拡大しました。 最新リリースに登場したものを詳しく見てみましょう。 行こう!
- Linuxで整数型のSSEを操作するためのSIMD演算子のサポートが追加されました。 これで、次の演算子が機能します。 +-* /&| ^ + =-= * = / =&= | = ^ = ==!=> <> = <=
以前にコンパイルされていない単純な例( immintrin.hを含めることを忘れないでください):
__m128i x,y,z; x = y + z;
これはLinuxでのみ機能することに注意してください。 Windowsコンパイラーは引き続き誓います: これらのsimdオペランドでは操作はサポートされていません
さらに、128ビットと256ビットのSIMDタイプのみがサポートされており、例のように2つのオペランドを持つフォームのみがサポートされています。 オペランド自体は同じ型である必要があります。たとえば、インテルSSE型は、 vector_size属性で宣言されたGNU型では使用できません。
- 標準のサポートが大幅に拡張されました。 おそらく、コンパイラ開発のこの方向は、新しいバージョンで最も重要なものの1つに帰することもできます。
そのため、C11標準のバージョン15(C ++ 11と混同しないでください)でバイナリリテラルのみがサポートされていた場合(プレフィックス0bまたは0Bで始まる)、今ではほとんどすべてがあります 。 最新のパブリックドラフト標準は、パブリックドメインにあります。 私はロシア語でC11についての良いレビュー記事を見つけられなかったので、各言語機能についてさらに詳しく書きます。 これが機能するためには、コンパイル中にWindowsでスイッチ/ Qstd = c11 、LinuxおよびMac OS Xで-std = c11を指定する必要があることを忘れないでください。
- データアライメント_Alignasおよび_Alignofの新しいキーワード(C ++ 11など)により、コンパイラに依存するソリューションから逃れることができます。
// cacheline 64 _Alignas(64) char cacheline[64]; printf("Alignment of char = %d\n", _Alignof(char));
データアライメントの必要性と重要性については以前に書いた 。
- _Genericキーワードを使用した、タイプに依存しない式。 これらは、C ++からのある種の「テンプレート」です。 たとえば、 sqrt(x)の平方根を抽出する次のマクロは、パラメーターxのタイプに応じてsqrtl(x) 、 sqrt(x)またはsqrtf(x)に変換されます。
#define sqrt(x) _Generic((x), long double: sqrtl, default: sqrt, float: sqrtf)(x)
しかし、 自分のペンでそれを実装するために一生懸命働く必要があった前に!
- _Noreturn関数指定子を使用すると、呼び出し元のコードに戻らない関数を宣言できます 。 これにより、戻り値を持たない関数に対するコンパイラーからの警告を避けることができ、「変更できない」関数でのみ実行できるいくつかの最適化を含めることができます。
_Noreturn void func (); // func never returns
- 新しいキーワード_Static_assertを使用すると、式がゼロに等しい場合にコンパイルエラーを生成できます。 簡単な例:
// static_assert(sizeof(int) < sizeof(char), "app requires sizeof(char) to be less than char"); error: static assertion failed with "app requires sizeof(char) to be less than char"
#ifおよび#errorディレクティブとは異なり、前処理中に見つけるのが難しいエラーをキャッチできます 。
- 匿名の構造と関連付け。 これは、匿名のアルコール依存症の非営利団体です...冗談です、ただあなたの集中力をチェックしました。 これらは、構造と関連付けをネストするために使用されます。 例:
struct T // C11 { int m; union // { char * index; int key; }; }; struct T t; t.key=1300; // key
- C11標準の特徴は、C言語でマルチスレッドを標準化することです。もちろん、開発者は長い間Cで並列処理の利点を使用していましたが、それでも、ライブラリや他の言語拡張機能を使用していました。 今では標準で綴られています。
そのため、インテル®コンパイラーがサポートする新しいキーワードの1つである_Thread_local 。 これを使用して、変数がスレッドに共通ではなく、各スレッドが独自のローカルコピーを取得するように指定できます。
- データアライメント_Alignasおよび_Alignofの新しいキーワード(C ++ 11など)により、コンパイラに依存するソリューションから逃れることができます。
- CおよびC ++標準では、括弧内の式の評価の優先順位を尊重する必要はありません。 たとえば、式A +(B + C)へのBとCの追加が主に実行されるという事実からはほど遠いため、数値結果に違いが生じます。 最後に、浮動小数点型の合計(再関連付け)の順序を変更する最適化を無効にするコンパイラオプションが登場しました。 現在、 -fprotect-parens (Linux * OSおよびOS X *)または/ Qprotect-parens (Windows *)オプションが使用されている場合、操作の順序は角括弧によって決定されます。 このオプションを使用すると、コードの実行が多少遅くなる場合があります。 デフォルトでは、コンパイラはこのオプションを有効にしません。
- バージョン15.0でC ++ 11のサポートを完全に実装したため、コンパイラ開発者は次のことに密接に取り組んでいます-C ++ 14は 、現在半数以上サポートされています。 C11と同様に、さまざまなバージョンのコンパイラで標準のさまざまな機能のサポートが追跡されるページがあります 。 Windows では/ Qstd = c ++ 14オプション、LinuxおよびMac OS X では-std = c ++ 14オプションを使用して、C ++ 14サポートを有効にできます。
したがって、新しいリリース以降、現在サポートされているものは次のとおりです。
- 一般化されたラムダ関数
- ラムダ関数の式キャプチャ
- 排出セパレーター
- 属性[[非推奨]]
- 関数の結論戻り型
- フィールド初期化子によるクラスの初期化の集約
標準のこれらの機能の詳細な説明は、ネットワーク、たとえばWikiやHabréの優れた投稿( P1およびP2 )で簡単に見つけることができます。
マクロ( Feature Test macros )のサポートも登場しました。これにより、コンパイラーによる標準の特定の機能のサポート、またはヘッダーの存在を判別できます。 この機能はまだC ++ 14標準ではなく、TRでのみ提供されていますが、すぐに提供される予定です。 簡単な例:
#if __cpp_binary_literals int const packed_zero_to_three = 0b00011011; #else int const packed_zero_to_three = 0x1B; #endif
バイナリリテラルがコンパイラでサポートされているかどうかを非常に簡単に判断できます。 より詳細に(たとえば、マクロ名__cpp_binary_literals 、 __cpp_digit_separatorsなどのプレートを見つけるために)、 ここでこの便利な機能に慣れることができます 。
- 非常に便利なプラグマblock_loopディレクティブが追加されました。これにより、ループブロッキングで最適化を制御できます。これについては、この投稿で詳しく説明しました。
- OpenMP 4.1標準の次のバージョン( テクニカルレポート3 )のサポートにより、Xeon Phiコプロセッサーおよびその他の可能なアクセラレーターへの計算のオフライン(アップロード)の操作の可能性が基本的に拡張されます。
- 変数をコプロセッサーにマップするために、新しいomp target enter dataディレクティブが登場しました( mapオプションに設定してallocすることが可能です)。 ompターゲットディレクティブが変数をマップし、デバイスでコードを実行する場合、 ompターゲット データはデータのみを処理します。 したがって、unmap'a変数用のompターゲット出口データディレクティブもあります( mapオプションにfrom 、 release 、およびdeleteを指定することが可能です)。
- 非同期コード実行機能の改善。 ターゲット領域はタスクになったため、タスクを操作するための既存のモデルとomp taskディレクティブのnowaitオプションを使用して、非同期オフラインが可能です。
- omp taskディレクティブのdependオプション。これにより、依存関係のあるアンロードが可能になります
- マップオプションの新しいalwaysおよびdelete修飾子
OpenMP 4.1のフレームワーク内で、アクセラレーターを使用する可能性が大幅に拡大したという事実に加えて、Intelコンパイラー固有のコプロセッサーを使用した実装も改善されました。
- 以前、フォームptr-> fieldでコプロセッサーへのアップロード用のポインターを介してオブジェクトフィールドを渡すことが不可能だった場合、この制限は削除されました。 同時に、フィールドがポインターである構造を転送することが可能になりました。 この場合の構造自体はビット単位で送信され、ポインターはコピーされますが、それらが指す構造のフィールドはコピーされません。
- targetptrとpreallocated 修飾子を使用して、ホストにメモリを割り当てずに、コプロセッサにのみメモリを割り当てることが可能になりました。
- ストリームの概念(およびプラグマオフロードディレクティブの新しいストリームオプション)が登場しました-アップロード用の論理キュー。 その助けを借りて、1つのCPUストリームからXeon Phiの複数の独立した計算をアンロードできるようになりました。 手順は次のとおりです。
最初に、 _Offload_stream_create API関数を使用してストリームを作成します。
OFFLOAD_STREAM* handle = _Offload_stream_create( int device, // Intel MIC Architecture device number int number_of_cpus); // Threads allocated to the stream
オフロードディレクティブとストリームオプションを使用してストリームにオフストリームし、アンロードを識別するためのシグナル値を示します。 これは、特定のオフラインが完了したかどうかを判断するのに役立ちます。
// Issue offload to a stream and identify with signal value s1 #pragma offload … stream(handle) signal(s1) { … } … // Issue offload to a stream and identify with signal value s2 #pragma offload … stream(handle) signal(s2) { … } … // Check if offload with signal value s1 has completed if (_Offload_signaled(s1)) …
詳細については、新しいバージョンのリリースで大幅に拡張されたドキュメントをご覧ください。
上記のすべてに加えて、当然すべてのライブラリ(Intel IPP、TBB、MKL)の新しいバージョンが登場しました。そこでは、多くの興味深いものも見つけることができます。 さらに、よく知られている「3文字」のものに加えて、新しいIntel DAALライブラリが追加されました。これについては、 別の投稿で既に説明しました。 レビューの外には、インテルCilk Plusの変更、コンパイラーからの注釈付きの新しいリスト、コンパイル速度の改善、さらに多くのマイナーな改善がありました。 最新バージョンを試用します。これは、30日間の試用ライセンスで(機能制限なしで、完全にサポートされた状態で)引き続き利用でき、経験を共有してください。