ホームページ >バックエンド開発 >C++ >最新の x86-64 Intel CPU でサイクルあたり 4 FLOP を達成するにはどうすればよいですか?

最新の x86-64 Intel CPU でサイクルあたり 4 FLOP を達成するにはどうすればよいですか?

Susan Sarandon
Susan Sarandonオリジナル
2024-12-14 08:42:10150ブラウズ

How to Achieve 4 FLOPs Per Cycle on Modern x86-64 Intel CPUs?

サイクルごとに理論上の最大 4 FLOP を達成するにはどうすればよいですか?

理論的には 4 つの浮動小数点のピーク パフォーマンスを達成することが可能です最新の x86-64 Intel CPU でのサイクルごとの演算 (倍精度)。以下を利用します。テクニック:

SSE 命令用のコードの最適化

  • 複数のデータ要素の並列処理を可能にする SSE (ストリーミング SIMD 拡張機能) 命令を使用します。
  • 最適な SSE のためにコードが適切に調整されていることを確認しますパフォーマンス。

ループのアンロールとインターリーブ

  • 内部ループをアンロールして命令レベルの並列性を向上させます。
  • インターリーブは乗算と加算を行います。 CPU のパイプラインを利用する機能。

操作を 3 つでグループ化

  • 一部の Intel CPU の実行ユニットに一致するように、操作を 3 つのグループに配置します。これにより、add 命令と mul 命令を交互に実行して、スループットを最大化できます。

不要なストールと依存関係を回避します

  • ストールを回避するために、命令間のデータ依存関係を最小限に抑えます。 .
  • コンパイラの最適化 (-O3 以降) を使用して、不要な依存関係を特定して削除するのに役立ちます。

サンプル コード

次のコード スニペットは、Intel Core i5 および Core i7 CPU でピークに近いパフォーマンスを達成する方法を示しています。 :

#include <emmintrin.h>
#include <omp.h>
#include <iostream>
using namespace std;

typedef unsigned long long uint64;

double test_dp_mac_SSE(double x, double y, uint64 iterations) {
    register __m128d r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, rA, rB, rC, rD, rE, rF;

    // Generate starting data.
    r0 = _mm_set1_pd(x);
    r1 = _mm_set1_pd(y);

    r8 = _mm_set1_pd(-0.0);

    r2 = _mm_xor_pd(r0, r8);
    r3 = _mm_or_pd(r0, r8);
    r4 = _mm_andnot_pd(r8, r0);
    r5 = _mm_mul_pd(r1, _mm_set1_pd(0.37796447300922722721));
    r6 = _mm_mul_pd(r1, _mm_set1_pd(0.24253562503633297352));
    r7 = _mm_mul_pd(r1, _mm_set1_pd(4.1231056256176605498));
    r8 = _mm_add_pd(r0, _mm_set1_pd(0.37796447300922722721));
    r9 = _mm_add_pd(r1, _mm_set1_pd(0.24253562503633297352));
    rA = _mm_sub_pd(r0, _mm_set1_pd(4.1231056256176605498));
    rB = _mm_sub_pd(r1, _mm_set1_pd(4.1231056256176605498));

    rC = _mm_set1_pd(1.4142135623730950488);
    rD = _mm_set1_pd(1.7320508075688772935);
    rE = _mm_set1_pd(0.57735026918962576451);
    rF = _mm_set1_pd(0.70710678118654752440);

    uint64 iMASK = 0x800fffffffffffffull;
    __m128d MASK = _mm_set1_pd(*(double*)&iMASK);
    __m128d vONE = _mm_set1_pd(1.0);

    uint64 c = 0;
    while (c < iterations) {
        size_t i = 0;
        while (i < 1000) {
            // Main computational loop

            r0 = _mm_mul_pd(r0, rC);
            r1 = _mm_add_pd(r1, rD);
            r2 = _mm_mul_pd(r2, rE);
            r3 = _mm_sub_pd(r3, rF);
            r4 = _mm_mul_pd(r4, rC);
            r5 = _mm_add_pd(r5, rD);
            r6 = _mm_mul_pd(r6, rE);
            r7 = _mm_sub_pd(r7, rF);
            r8 = _mm_mul_pd(r8, rC);
            r9 = _mm_add_pd(r9, rD);
            rA = _mm_mul_pd(rA, rE);
            rB = _mm_sub_pd(rB, rF);

            r0 = _mm_add_pd(r0, rF);
            r1 = _mm_mul_pd(r1, rE);
            r2 = _mm_sub_pd(r2, rD);
            r3 = _mm_mul_pd(r3, rC);
            r4 = _mm_add_pd(r4, rF);
            r5 = _mm_mul_pd(r5, rE);
            r6 = _mm_sub_pd(r6, rD);
            r7 = _mm_mul_pd(r7, rC);
            r8 = _mm_add_pd(r8, rF);
            r9 = _mm_mul_pd(r9, rE);
            rA = _mm_sub_pd(rA, rD);
            rB = _mm_mul_pd(rB, rC);

            r0 = _mm_mul_pd(r0, rC);
            r1 = _mm_add_pd(r1, rD);
            r2 = _mm_mul_pd(r2, rE);
            r3 = _mm_sub_pd(r3, rF);
            r4 = _mm_mul_pd(r4, rC);
            r5 = _mm_add_pd(r5, rD);
            r6 = _mm_mul_pd(r6, rE);
            r7 = _mm_sub_pd(r7, rF);
            r8 = _mm_mul_pd(r8, rC);
            r9 = _mm_add_pd(r9, rD);

以上が最新の x86-64 Intel CPU でサイクルあたり 4 FLOP を達成するにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。