組み込みアルゴリズム移植最適化研究ノート2-SIMDプログラミング(単一の命令ストリームと複数のデータストリーム)

1.SIMDの概念

単一命令複数データ、つまり、単一命令ストリームと複数データストリームは、複数のデータストリームに対して同じ操作を実行します。単一命令、複数データ(SIMD)は、並列コンピューターの一種です(Flynn分類による)。複数のデータポイントで同じ操作を同時に(同時に)実行できる複数の処理要素を備えたコンピューターについて説明します。この種のマシンは、データレベルの並列処理(並行性ではない)を利用します。特定の時点では、命令は1つだけですが、複数の同時(同時)計算、つまり並列計算があります。SIMDは、デジタル画像のコントラストの調整やデジタルオーディオの音量の調整など、いくつかの一般的なタスクに特に適しています。最新のCPU設計には、マルチメディア使用のパフォーマンスを向上させるためのSIMD命令が含まれています。SIMDとSIMTを混同しないでください。前者はデータレベルで機能し、後者はスレッドを使用します。簡単な例は、ベクトルの加算と減算です。

MIMDとの違い
SIMDには単一のグローバルコントロールユニットがありますが、後者には複数のコントロールユニット+処理要素があります。

第二に、SIMDの適用

  • 画像処理
  • オーディオ
  • 科学計算
  • データベースのデータ並列コンピューティング。

SIMDを適用するタイミング

  • 通常のデータアクセスモード:データはメモリに継続的に保存されます。
  • 短いデータ型
  • ストリーミングデータ処理
    ..。

3つ目は、SIMDを使用することの長所と短所です。

利点

  • 並行性が高くなります。
  • 設計は比較的単純です(MIMDと比較する必要があり、機能ユニットを繰り返すだけで済みます)。
    チップサイズが小さいです。

不利益

  • プログラマーは、開発時にハードウェアに明示的に連絡する必要があります。

第四に、SIMD並列処理の問題

SIMD並列開発では、複数の同一の算術演算を1つのSIMD演算に簡略化できます。複数のフェッチ/保存結果演算を、より広いメモリの1つの演算に変えることができます(メモリが連続している必要がある場合)。

5、SIMDプログラミングの複雑さ

低レベルのプログラミング要件:

  • データを整列させる必要があります。
  • データは連続領域に保存されます。
  • 制御フローの問題により、複雑さが増す可能性があります。

6、SIMD開発

いわゆるSIMD命令は、単一命令の複数データ、つまり単一命令の複数データ操作を指し、その目的は、CPUがデータの並列処理を実現し、操作効率を向上させるのを支援することです。

MMX

MMXは、57個の命令で構成されるSIMDマルチメディア命令セットです。MMXは64ビットレジスタを2個の32ビットまたは8個の8ビットレジスタとして扱い、シェーピング計算のみを処理できます。このような64ビットレジスタには8つのグループがあり、個別に名前が付けられています。 MM0〜MM7です。これらのレジスタはMMX用に個別に設定されていませんが、借用されたFPUレジスタは、演算用の浮動小数点レジスタを占有します(64ビットMMXレジスタは、実際には浮動小数点レジスタのエイリアスです)。そのため、MMX命令と浮動小数点演算は次の場所では機能しません。同時に。MMXと浮動小数点モードの切り替えにかかる時間を短縮するために、プログラマーはモード切り替えの数を可能な限り削減しようとします。つまり、これら2つの操作はアプリケーションで相互に排他的です。

SSE

SSEのフルネームはストリーミングSIMD拡張命令で、MMXに基づいて開発されたSIMD命令セットです。フローティングポイントレジスタを占有しなくなりましたが、別個の128ビットXMMレジスタを使用します。これに基づいて、SSE2 / SSE3 / SSE4命令セットが開発されました。SSE2はさらに倍精度浮動小数点数をサポートします。レジスタ長は変更されないため、2つの倍精度浮動小数点計算または4つの単精度浮動小数点計算しかサポートできません。さらに、これに整数計算を実装します。レジスタのセット。、したがって、MMXを置き換えます。SSE3は、より複雑な算術計算をサポートしています。SSE4はさらに命令を追加し、データ移動に懸命に取り組み、整列されていないデータ移動をサポートし、スーパーシャッフルエンジンを追加します。

AVX

SSE命令セットに基づいて、128ビットXMMレジスタが256ビットYMMレジスタに拡張され、256ビットベクトル計算がサポートされます。AVXは、下位のSSE / SSE2 / SSE3 / SSE4と完全に互換性があります。 YMMレジスタの128ビットはXMMレジスタです。

3DNow!

3DNow!は、Intel MMXレジスタの論理拡張です。MMXは並列整数演算のみを提供し、3DNow!は並列浮動小数点演算を実装します。3DNow!は、既存のMMX命令セットに基づいて、MMXに必要なコンテキスト変換を必要とせずに、整数コードと浮動小数点コードを使用した混合演算を実現できます。

7つの関連するコード例

CPUでサポートされているSIMD命令セットを表示する

cat /proc/cpuinfo

コンパイラでサポートされているSIMD命令セットを確認できます

flags		: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts mmx fxsr sse sse2 ss ht syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon pebs bts nopl xtopology tsc_reliable nonstop_tsc aperfmperf eagerfpu pni pclmulqdq ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch fsgsbase tsc_adjust bmi1 avx2 smep bmi2 invpcid rdseed adx smap xsaveopt dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp

ここに画像の説明を挿入

GCCプロセッサでサポートされているSIMD命令セットを表示する

gcc -march=native -c -Q --help=target

サポートされているSIMD命令セットとサポートされていないSIMD命令セットを確認できます。

diyun@diyun-virtual-machine:~/桌面$ gcc -march=native -c -Q --help=target
The following options are target specific:
  -m128bit-long-double        		[disabled]
  -m32                        		[disabled]
  -m3dnow                     		[disabled]
  -m3dnowa                    		[disabled]
  -m64                        		[enabled]
  -m80387                     		[enabled]
  -m8bit-idiv                 		[disabled]
  -m96bit-long-double         		[enabled]
  -mabi=                      		sysv
  -mabm                       		[enabled]
  -maccumulate-outgoing-args  		[disabled]
  -maddress-mode=             		short
  -madx                       		[enabled]
  -maes                       		[enabled]
  -malign-double              		[disabled]
  -malign-functions=          		0
  -malign-jumps=              		0
  -malign-loops=              		0
  -malign-stringops           		[enabled]
  -mandroid                   		[disabled]
  -march=                     		core-avx2
  -masm=                      		att
  -mavx                       		[enabled]
  -mavx2                      		[enabled]
  -mavx256-split-unaligned-load 	[disabled]
  -mavx256-split-unaligned-store 	[disabled]
  -mbionic                    		[disabled]
  -mbmi                       		[enabled]
  -mbmi2                      		[enabled]
  -mbranch-cost=              		0
  -mcld                       		[disabled]
  -mcmodel=                   		32
  -mcpu=                      		
  -mcrc32                     		[disabled]
  -mcx16                      		[enabled]
  -mdispatch-scheduler        		[disabled]
  -mf16c                      		[enabled]
  -mfancy-math-387            		[enabled]
  -mfentry                    		[enabled]
  -mfma                       		[enabled]
  -mfma4                      		[disabled]
  -mforce-drap                		[disabled]
  -mfp-ret-in-387             		[enabled]
  -mfpmath=                   		387
  -mfsgsbase                  		[enabled]
  -mfunction-return=          		keep
  -mfused-madd                		
  -mfxsr                      		[enabled]
  -mglibc                     		[enabled]
  -mhard-float                		[enabled]
  -mhle                       		[disabled]
  -mieee-fp                   		[enabled]
  -mincoming-stack-boundary=  		0
  -mindirect-branch-register  		[disabled]
  -mindirect-branch=          		keep
  -minline-all-stringops      		[disabled]
  -minline-stringops-dynamically 	[disabled]
  -mintel-syntax              		
  -mlarge-data-threshold=     		0x10000
  -mlong-double-64            		[disabled]
  -mlong-double-80            		[enabled]
  -mlwp                       		[disabled]
  -mlzcnt                     		[enabled]
  -mmmx                       		[disabled]
  -mmovbe                     		[enabled]
  -mms-bitfields              		[disabled]
  -mno-align-stringops        		[disabled]
  -mno-fancy-math-387         		[disabled]
  -mno-push-args              		[disabled]
  -mno-red-zone               		[disabled]
  -mno-sse4                   		[disabled]
  -momit-leaf-frame-pointer   		[disabled]
  -mpc32                      		[disabled]
  -mpc64                      		[disabled]
  -mpc80                      		[disabled]
  -mpclmul                    		[enabled]
  -mpopcnt                    		[enabled]
  -mprefer-avx128             		[disabled]
  -mpreferred-stack-boundary= 		0
  -mprfchw                    		[enabled]
  -mpush-args                 		[enabled]
  -mrdrnd                     		[enabled]
  -mrdseed                    		[enabled]
  -mrecip                     		[disabled]
  -mrecip=                    		
  -mred-zone                  		[enabled]
  -mregparm=                  		0
  -mrtd                       		[disabled]
  -mrtm                       		[disabled]
  -msahf                      		[enabled]
  -msoft-float                		[disabled]
  -msse                       		[enabled]
  -msse2                      		[enabled]
  -msse2avx                   		[disabled]
  -msse3                      		[enabled]
  -msse4                      		[enabled]
  -msse4.1                    		[enabled]
  -msse4.2                    		[enabled]
  -msse4a                     		[disabled]
  -msse5                      		
  -msseregparm                		[disabled]
  -mssse3                     		[enabled]
  -mstack-arg-probe           		[disabled]
  -mstackrealign              		[enabled]
  -mstringop-strategy=        		[default]
  -mtbm                       		[disabled]
  -mtls-dialect=              		gnu
  -mtls-direct-seg-refs       		[enabled]
  -mtune=                     		generic
  -muclibc                    		[disabled]
  -mveclibabi=                		[default]
  -mvect8-ret-in-mem          		[disabled]
  -mvzeroupper                		[disabled]
  -mx32                       		[disabled]
  -mxop                       		[disabled]
  -mxsave                     		[enabled]
  -mxsaveopt                  		[enabled]

  Known assembler dialects (for use with the -masm-dialect= option):
    att intel

  Known ABIs (for use with the -mabi= option):
    ms sysv

  Known code models (for use with the -mcmodel= option):
    32 kernel large medium small

  Valid arguments to -mfpmath=:
    387 387+sse 387,sse both sse sse+387 sse,387

  Known indirect branch choices (for use with the -mindirect-branch=/-mfunction-return= options):
    keep thunk thunk-extern thunk-inline

  Known vectorization library ABIs (for use with the -mveclibabi= option):
    acml svml

  Known address mode (for use with the -maddress-mode= option):
    long short

  Valid arguments to -mstringop-strategy=:
    byte_loop libcall loop rep_4byte rep_8byte rep_byte unrolled_loop

  Known TLS dialects (for use with the -mtls-dialect= option):
    gnu gnu2

ここに画像の説明を挿入

SIMD命令の使用例

単純な浮動小数点行列の乗算(コンパイラーの最適化)
float_matrix_mutiply.c:

#include <stdio.h>
#include <stdio.h>
void printf_matrix(int x,int y,double a[x][y])
{
    
    
        for(int i=0;i<x;i++){
    
    
                for(int j=0;j<y;j++){
    
    
                        printf("%lf ",a[i][j]);
                }
                printf("\n");
        }
}

int main()
{
    
    
        int M=2,N=3,P=4;
        double matrix1[M][N];
        double matrix2[N][P];

        FILE *fp1,*fp2;
        fp1 = fopen("./matrix1","r");
        fp2 = fopen("./matrix2","r");

        int i = 0;
        while(!feof(fp1)){
    
    
                fscanf(fp1,"%lf %lf %lf",&matrix1[i][0],&matrix1[i][1],&matrix1[i][2]);
                i++;
        }
        printf("The first matrix is:\n");
        printf_matrix(M,N,matrix1);

        int j = 0;
        while(!feof(fp2)){
    
    
                fscanf(fp2,"%lf %lf %lf %lf",&matrix2[j][0],&matrix2[j][1],&matrix2[j][2],&matrix2[j][3]);
                j++;
        }
        printf("The second matrix is:\n");
        printf_matrix(N,P,matrix2);

        double result[M][P];
        for(int i=0;i<M;i++){
    
    
                for(int k=0;k<P;k++){
    
    
                        for(int j=0;j<N;j++){
    
    
                                result[i][k] += matrix1[i][j]*matrix2[j][k];
                        }
                }
        }
        printf("The matrix mutilpy result is:\n");
        printf_matrix(M,P,result);
}

コンパイル:

gcc float_matrix_mutiply.c -o float_matrix_mutiply -msse -mfpmath=sse -march=native

逆コンパイルは、xmmレジスタやmovsdなどのSIMD命令が使用されていることを示しています:

diyun@diyun-virtual-machine:~/桌面/0205_test$ objdump -d float_matrix_mutiply  |grep xmm
  400725:	c5 fb 10 45 c8       	vmovsd -0x38(%rbp),%xmm0
  400d9a:	c5 fb 10 0c d0       	vmovsd (%rax,%rdx,8),%xmm1
  400dc3:	c5 fb 10 14 d0       	vmovsd (%rax,%rdx,8),%xmm2
  400dec:	c5 fb 10 04 d0       	vmovsd (%rax,%rdx,8),%xmm0
  400df1:	c5 eb 59 c0          	vmulsd %xmm0,%xmm2,%xmm0
  400df5:	c5 f3 58 c0          	vaddsd %xmm0,%xmm1,%xmm0
  400e16:	c5 fb 11 04 d0       	vmovsd %xmm0,(%rax,%rdx,8)

ここに画像の説明を挿入

優先:
1、https://blog.csdn.net/sinat_26210035/article/details/88773961?utm_medium = distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.control&depth_1-utm_source = distribute.pc_relevant_t0.none-task-ブログ-BlogCommendFromMachineLearnPai2-1.control

2、https://blog.csdn.net/Rosalind_Xu/article/details/89576595?utm_medium = distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.control&depth_1-utm_source = distribute.pc_relevant_t0.none-task-blog- BlogCommendFromMachineLearnPai2-1.control

3、https://zhuanlan.zhihu.com/p/71266408
4、https://www.cnblogs.com/xidian-wws/p/11023762.html
5、HTTPS://blog.csdn.net/weixin_42826139/記事/詳細/ 86313717

おすすめ

転載: blog.csdn.net/mao_hui_fei/article/details/113804994