以前は、この質問に対する答えは「いいえ」でした。しかし、2017 年現在、状況は変わりつつあります。
ただし、先に進む前に、背景となる用語について説明します。
- フルワード算術
- 部分単語算術
フルワード演算:
これは、数値が32 ビットまたは 64 ビットの整数の配列を使用して基数 2 32または 2 64で格納される標準的な表現です。多くの bignum ライブラリとアプリケーション (GMP を含む) は、この表現を使用します。
フルワード表現では、すべての整数に固有の表現があります。比較などの操作は簡単です。しかし、加算のようなものは、キャリー伝搬が必要なため、より困難です。
bignum 算術のベクトル化をほとんど不可能にしているのは、このキャリー伝搬です。
部分語算術
これは、数値がハードウェアのワードサイズよりも小さい基数を使用する、あまり使用されない表現です。たとえば、各 64 ビット ワードに 60 ビットのみを配置します。または1,000,000,000
、10 進演算に 32 ビット ワード サイズの base を使用します。
GMP の作成者はこれを「ネイル」と呼び、「ネイル」は単語の未使用部分です。
以前は、部分語演算の使用は、非バイナリ ベースで動作するアプリケーションにほとんど制限されていました。しかし、今日では、キャリーの伝搬を遅らせることができるという点で、より重要になってきています。
全語演算の問題:
フルワード演算のベクトル化は、歴史的に失われた原因でした:
- SSE/AVX2 はキャリー伝搬をサポートしていません。
- SSE/AVX2 には 128 ビットの加減算がありません。
- SSE/AVX2 には、64 x 64 ビットの整数乗算はありません。*
*AVX512-DQ は、下位半分の 64x64 ビット乗算を追加します。しかし、まだ上半分の命令はありません。
さらに、x86/x64 には、bignum 用の特殊なスカラー命令がたくさんあります。
- キャリー付き加算:
adc
, adcx
, adox
.
- ダブルワード乗算: シングルオペランド
mul
and mulx
.
これを考慮すると、bignum-add と bignum-multiply の両方で、SIMD が x64 でスカラーを打ち負かすことは困難です。SSEまたはAVXでは絶対にありません。
AVX2 では、データを再配置して、4 つの SIMD レーンのそれぞれで同じ長さの 4 つの異なる(独立した) 乗算の「垂直ベクトル化」を有効にすると、SIMD はスカラー bignum-multiply とほぼ競合します。
AVX512 は、垂直方向のベクトル化を想定して、再び SIMD を支持するように物事を傾けます。
しかし、ほとんどの場合、bignum の「水平方向のベクトル化」は、(同じサイズの) 多数の bignum があり、「垂直」にするためにそれらを転置するコストを負担できない限り、大部分は失われた原因のままです。
部分単語演算のベクトル化
部分ワード演算では、追加の「ネイル」ビットにより、キャリーの伝播を遅らせることができます。
したがって、単語をオーバーフローしない限り、SIMD add/sub は直接実行できます。多くの実装では、部分単語表現は符号付き整数を使用して、単語が負になることを許可します。
(通常) キャリーアウトを実行する必要がないため、部分ワードの SIMD 加算/減算は、垂直方向と水平方向の両方のベクトル化された bignum で同等に効率的に実行できます。
水平方向にベクトル化された bignum のキャリーアウトは、次のレーンに釘を移動するだけなので、まだ安価です。ほとんど同じである 2 つの数値を比較する必要がない限り、釘のビットを完全にクリアして一意の表現に到達するための完全なキャリーアウトは、通常は必要ありません。
部分ワード演算では、ネイル ビットを処理する必要があるため、乗算はより複雑になります。しかし、add/sub と同様に、水平方向にベクトル化された bignum に対しても効率的に実行できます。
AVX512-IFMA (Cannonlake プロセッサに付属) には、52 x 52 ビット乗算 (おそらく FPU ハードウェアを使用) の完全な 104 ビットを与える命令があります。これは、1 ワードあたり 52 ビットを使用する部分ワード表現で非常にうまく機能します。
FFT を使用した大きな乗算
bignum が非常に大きい場合、乗算は高速フーリエ変換 (FFT)を使用して最も効率的に実行されます。
FFT は独立した で動作するため、完全にベクトル化できdouble
ます。これが可能なのは、基本的に、FFT が使用する表現が部分
語表現であるためです。
要約すると、bignum 演算のベクトル化は可能です。しかし、犠牲を払わなければなりません。
SSE/AVX が、表現やデータ レイアウトに根本的な変更を加えることなく、既存の bignum コードの一部を高速化できると期待している場合、それは実現しない可能性があります。
それでも、bignum 算術はベクトル化できます。
開示:
私は、大量の算術演算を行うy-cruncherの作成者です。