インテル® C++ コンパイラー 18.0 デベロッパー・ガイドおよびリファレンス

共有メモリーの使用

このトピックは、インテル® メニー・インテグレーテッド・コア (インテル® MIC) アーキテクチャーをターゲットとする場合にのみ適用されます。

共有メモリーの使用について

オフロード・ランタイム・システムは CPU とコプロセッサーの同じ仮想アドレスでメモリーのセクションを保持します。_Cilk_shared キーワードを使用することで、この共有メモリーを次のように使用できます。

共有変数について

コンパイラーは、次のような共有変数を割り当てます。

共有変数のアドレスは同じであるため、同じアドレス共有変数へのポインターには CPU とコプロセッサーで同じ値が含まれます。このため、オフロードコードをリンクされたデータ構造で容易に操作できます。メモリーは、オフロードの呼び出しでのみ CPU とコプロセッサー間で同期されます。

共有変数の条件付き制御

インテル® MIC アーキテクチャー上で実行するようにコンパイルする場合は、共有変数を条件付きで制御できません。

変数が _Cilk_shared と表記されると、変数のメモリー割り当てはスタティックではなくダイナミックで行われます。ホストが割り当てるメモリーは、ホストとコプロセッサーが共有するメモリー空間内のみです。プログラムをコンパイルすると、ホストは共有メモリーをダイナミックに作成するコードを生成します。このため、ホストが共有変数を見ない場合、変数のメモリーを割り当てません。メモリーが共有空間に割り当てられないため、コプロセッサーがこのメモリーにアクセスしようとすると、不正なアクセスが発生します。

ホストは共有変数にメモリーを割り当てるため、ホストが変数を使用しない場合でも、ホストが変数を見えるようにする必要があります。

例えば、次のコードは変数がコプロセッサー用に条件付きでコンパイルされているため正しくありません。このため、ホストで変数のメモリーを割り当てるコードは生成されません。

#ifdef __MIC__
_Cilk_shared int res;
#endif

変数をコプロセッサー用に条件付きでコンパイルすると、ホストは変数にアクセスしないため、_Cilk_shared キーワードは必要ありません。ホストとコプロセッサー間でデータを共有する場合のみ、_Cilk_shared を使用します。

共有関数について

デフォルトでは、コンパイラーは 2 つのバイナリーファイルをビルドします。

CPU バージョンのみビルドするには、[Q]offload オプションの否定形を使用します。

共有メモリー管理関数

_Cilk_shared および _Cilk_offload キーワードで操作する共有メモリーの割り当てと解放には、次の関数を利用します。これらの関数は、インテル® MIC アーキテクチャー・ベースのハードウェアがシステムにない場合、またはインテル® メニーコア・プラットフォーム・ソフトウェア・スタック (インテル® MPSS) がロードされていない場合、標準の malloc または free バージョンを使用します。

共有メモリー・アロケーター

デフォルトでは、標準 C++ ライブラリーのコンテナーは非共有メモリーを割り当てます。コンテナーのオブジェクトが _Cilk_shared と表記されると、そのデータメンバーは共有メモリーに割り当てられます。ただし、データがアクセスするメモリーは共有されません。このメモリーを共有できるようにするため、shared_allocator<T> クラス・テンプレートを使用します。shared_allocator<T> クラス・テンプレートは offload.h で定義されています。

共有メモリー・アロケーターの例

#pragma offload_attribute (push, _Cilk_shared) 
#include <vector> 
#include <offload.h> 
#pragma offload_attribute (pop) 
#include <stdio.h> 

using namespace std;

// オフロードの共有アロケーターを使用するための typedef vector
typedef vector<int, __offload::shared_allocator<int> > shared_vec_int;

_Cilk_shared shared_vec_int * _Cilk_shared v;

_Cilk_shared int test_result() {

int result = 1;

for (int i = 0; i < 5; i++) {
      if ((*v)[i] != i) {
        result = 0;
      }
  }

  return result;
}

int main()
{
  int result;

  // new を使用して共有メモリー空間にオブジェクトを構築
  v = new (_Offload_shared_malloc(sizeof(vector<int>))) _Cilk_shared vector<int,
                                              __offload::shared_allocator<int> >(5);

  for (int i = 0; i < 5; i++) {
      (*v)[i] = i;
  }
  result = _Cilk_offload test_result();

  if (result != 1)
      printf("Failed\n");
  else
      printf("Passed\n");

  return 0;
}

関連情報