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


回答:


225

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

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

(最新のハードウェアが直接サポートする可能性が最も高いため、4を選択しました。「ベクトル化」という用語は、ループを完全に抽象化し、要素ではなく配列の操作を説明するだけの高レベルのソフトウェア変換を表すためにも使用されますそれらを構成する)


ベクトル化とループ展開の違い: 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」は、コンパイラーがベクトル命令を指定するために使用する組み込み関数のプレースホルダーです。一部のコンパイラは、このような非常に単純なループを自動ベクトル化できることに注意してください。これは、多くの場合、コンパイルオプションで有効にできます。より複雑なアルゴリズムでも、優れたベクトルコードを生成するには、プログラマーの助けが必要です。


11
これとループの巻き戻し/巻き戻しの違いは何ですか?
ジェレミー・パウエル

1
コンパイラーが展開されたループを自動ベクトル化するより簡単な仕事をするのは本当ではありませんか?
Nikos Athanasiou

@NikosAthanasiou:もっともらしいことですが、どちらのループも非常に単純であるため、一般的に言えば、コンパイラはどちらかのループを自動ベクトル化できるはずです。
Stephen Canon

1
@StephenCanon一部の行がベクトル化されているかどうかをどのように確認できますか?objdumpを使用する場合、objdumpの出力で何を探しますか?
user1823664 2017年

3
@Shuklaswag:ベクトル化はコンパイラーができることですが、プログラマーが明示的に行うことでもあります。OSは関与していません。
スティーブンキャノン

32

ベクトル化は、スカラープログラムをベクトルプログラムに変換するための用語です。ベクトル化されたプログラムは単一の命令から複数の演算を実行できますが、スカラーは一度にオペランドのペアのみを操作できます。

ウィキペディアから:

スカラーアプローチ:

for (i = 0; i < 1024; i++)
{
   C[i] = A[i]*B[i];
}

ベクトル化されたアプローチ:

for (i = 0; i < 1024; i+=4)
{
   C[i:i+3] = A[i:i+3]*B[i:i+3];
}

それは本質的にスカラーアプローチと同じではありませんか?構文とループの進行は異なりますが、その下ではまだ4倍になっています。しかし、どういうわけか、おそらくCPUには、ベクトル化と呼ばれるいくつかのトリックを実行する命令が含まれています。
mskw 2017

ここで自分の質問に答えます。ベクトル化アプローチの構文は、コンパイラーがそれを認識すると、ベクトルを乗算する最適化されたCPU命令に変換します。SIMDのように。
mskw 2017

10

これは、1つのステップで数値のリスト、つまり「ベクトル」に対して単一の数学演算を実行する機能を指します。ベクトル化された算術が最初に登場したスーパーコンピューティングに関連する科学計算に関連しているため、Fortranでよく見られます。現在、ほとんどすべてのデスクトップCPUは、IntelのSSEなどのテクノロジーを通じて、何らかの形式のベクトル化された演算を提供しています。GPUは、ベクトル化された演算の形式も提供します。


7

ベクトル化は、膨大な量のデータを効率的に処理する必要がある科学計算で大いに使用されています。

実際のプログラミングアプリケーションでは、それがNUMPYで使用されていることを知っています(他のことがわかりません)

Numpy(pythonでの科学計算用のパッケージ)は、ベクトル化を使用してn次元配列を迅速に操作します。これは、配列を処理する組み込みのpythonオプションを使用すると、通常は遅くなります。

説明のトンがそこにあるが、HERE'S WHAT ベクトルは、のように定義されてnumpyののドキュメントページ

ベクトル化とは、コードに明示的なループやインデックスなどがないことを示します。もちろん、これらのことは、最適化され、コンパイル済みのCコードの「裏で」行われています。ベクトル化されたコードには、次のような多くの利点があります。

  1. ベクトル化されたコードはより簡潔で読みやすい

  2. コードの行数が少ないほど、一般的にバグが少ないことを意味します

  3. このコードは、標準の数学的表記にさらに似ています(通常、数学的構造を正しくコード化するのが簡単になります)

  4. ベクトル化により、より「Python的な」コードになります。ベクトル化を行わないと、コードが非効率で、forループを読み取るのが困難になります。


4

ベクトル化とは、簡単に言うと、アルゴリズムを最適化して、プロセッサでSIMD命令を利用できるようにすることです。

AVX、AVX2、およびAVX512は、1つの命令で複数のデータに対して同じ操作を実行する命令セット(インテル)です。たとえば。AVX512は、一度に16個の整数値(4バイト)を操作できることを意味します。つまり、16個の整数のベクトルがあり、各整数でその値を2倍にして、それに10を加算したい場合です。汎用レジスター[a、b、c]に値を16回ロードして同じ操作を実行するか、16個の値すべてをSIMDレジスター[xmm、ymm]にロードして操作を1回実行することができます。これにより、ベクターデータの計算を高速化できます。

ベクトル化では、SIMD演算を実行してプログラムを高速化できるようにデータを再構築することにより、これを有利に使用します。

ベクトル化の唯一の問題は、条件の処理です。条件は実行の流れを分岐させるからです。これはマスキングによって処理できます。条件を算術演算にモデル化する。例えば。100よりも大きい場合に値に10を追加する場合は、どちらでも可能です。

if(x[i] > 100) x[i] += 10; // this will branch execution flow.

または、条件を算術演算にモデル化して、条件ベクトルcを作成できます。

c[i] = x[i] > 100; // storing the condition on masking vector
x[i] = x[i] + (c[i] & 10) // using mask

これは非常に簡単な例ですが... cは、その値に基づいてバイナリ演算を実行するために使用するマスキングベクトルです。これにより、実行フローの分岐が回避され、ベクトル化が可能になります。

ベクトル化は並列化と同じくらい重要です。したがって、私たちはそれを可能な限り利用するべきです。現代のすべてのプロセッサには、重い計算ワークロード用のSIMD命令があります。ベクトル化を使用してこれらのSIMD命令を使用するようにコードを最適化できます。これは、最新のプロセッサで使用可能な複数のコアで実行するようにコードを並列化するのと似ています。

プラグマを使用してコードをベクトル化できるOpenMPについて触れておきます。私はそれを良い出発点と考えています。OpenACCについても同じことが言えます。


0

インテルの人は理解しやすいと思います。

ベクトル化は、一度に1つの値を操作することから、一度に一連の値を操作することにアルゴリズムを変換するプロセスです。最新のCPUは、単一の命令が複数のデータ(SIMD)に適用されるベクトル演算を直接サポートしています。

たとえば、512ビットレジスタを備えたCPUは、16個の32ビット単精度倍精度を保持し、単一の計算を実行できます。

一度に1つの命令を実行するよりも16倍高速です。これをスレッディングおよびマルチコアCPUと組み合わせると、桁違いのパフォーマンスの向上につながります。

リンクhttps://software.intel.com/en-us/articles/vectorization-a-key-tool-to-improve-performance-on-modern-cpus

Javaでは、2020年のJdk 15、または2021年のJDK 16の後半にこれを含めるオプションがあります。

https://bugs.openjdk.java.net/browse/JDK-8201271


-4

上記の2つの答えを参照してください。ベクトル化を行う理由は、これらの操作をスーパーコンピューターやマルチプロセッサーで簡単に実行できるため、パフォーマンスが大幅に向上することです。シングルプロセッサコンピュータでは、パフォーマンスは向上しません。


12
「シングルプロセッサコンピュータでは、パフォーマンスは向上しません」:正しくありません。最新のプロセッサーのほとんどは、ベクトル化(stephentyroneによって名前が付けられたSSE、Altivecなど)のハードウェアサポートを(制限付きで)備えているため、使用すると大幅なスピードアップを実現できます。
sleske 2009

おかげで、そのレベルでも並列化を実行できることを忘れていました。
ワタナベラリー、
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.