「ベクトル化」とは何ですか? 質問する

「ベクトル化」とは何ですか? 質問する

これまで、matlab、fortran などでこの用語に何度か遭遇しましたが、それが何を意味し、何をするのかについての説明は見つかりませんでした。そこで、ベクトル化とは何なのか、たとえば「ループがベクトル化される」とはどういう意味なのかを尋ねています。

ベストアンサー1

多くの CPU には、2 つ、4 つ、またはそれ以上のデータに同時に同じ操作を適用する「ベクター」または「SIMD」命令セットがあります。最新の x86 チップには SSE 命令があり、多くの PPC チップには「Altivec」命令があり、一部の ARM チップにも NEON と呼ばれるベクター命令セットがあります。

「ベクトル化」(簡略化)は、配列の 1 つの要素を N 回処理する代わりに、(たとえば)配列の 4 つの要素を同時に N/4 回処理するようにループを書き換えるプロセスです。

4 を選択したのは、これが最新のハードウェアが 32 ビットの float または int を直接サポートする可能性が最も高いためです。


ベクトル化とループ展開の違い: 2 つの配列の要素を追加し、その結果を 3 番目の配列に格納する次の非常に単純なループを考えてみましょう。

for (int i=0; i<16; ++i)
    C[i] = A[i] + B[i];

このループを展開すると、次のようになります。

for (int i=0; i<16; i+=4) {
    C[i]   = A[i]   + B[i];
    C[i+1] = A[i+1] + B[i+1];
    C[i+2] = A[i+2] + B[i+2];
    C[i+3] = A[i+3] + B[i+3];
}

一方、ベクトル化すると、次のようになります。

for (int i=0; i<16; i+=4)
    addFourThingsAtOnceAndStoreResult(&C[i], &A[i], &B[i]);

ここで、「addFourThingsAtOnceAndStoreResult」は、コンパイラがベクトル命令を指定するために使用する組み込み関数のプレースホルダーです。


用語:

最新の ATD (事前コンパイラ) のほとんどは、このような非常に単純なループを自動的にベクトル化できます。これは、多くの場合、コンパイル オプション ( など、最新の C および C++ コンパイラでは、完全な最適化でデフォルトでオンgcc -O3 -march=native) によって有効にできます。OpenMP は#pragma omp simd、特にベクトル化で FP 数学が結合的であると仮定する必要がある FP 配列の合計などの「リダクション」ループの場合に、コンパイラにヒントを与えるのに役立つことがあります。

より複雑なアルゴリズムでは、優れたベクトルコードを生成するためにプログラマーの助けが必要です。これを手動ベクトル化と呼び、多くの場合、x86のような組み込み関数を使用して_mm_add_ps単一のマシン命令にマッピングします。Intel CPU の SIMD プレフィックス合計またはSIMDを使用して文字の出現回数をカウントする方法または、次のような短いループしない問題にSIMDを使用することもできます。9 文字の数字を int または unsigned int に変換する最も高速な方法または2進整数を16進文字列に変換するにはどうすればいいですか?

「ベクトル化」という用語は、ループを完全に抽象化し、配列を構成する要素ではなく配列の操作のみを記述する、より高レベルのソフトウェア変換を説明する場合にも使用されます。たとえば、C = A + BC や C++ とは異なり、配列または行列の場合にそれを許可する言語で記述します。このような低レベル言語では、ループを手動で記述する代わりに、BLAS または Eigen ライブラリ関数を呼び出すことをベクトル化されたプログラミング スタイルとして説明できます。この質問に対する他の回答では、ベクトル化の意味と高レベル言語に焦点を当てています。

おすすめ記事