ベクトルとスカラーの積

fract16型のベクトルとfract16型の固定小数点乗算を行います。

ベクトル乗算同様にC++言語を使って記述したのが以下のプログラムです。

void stk::mul( fract16 dst[], fract16 src1[], fract16 src2, int count )
{
#pragma no_alias
#pragma different_banks
        for ( int i=0; i<count; i++ )
                dst[i] = multr_fr1x16( src1[i], src2);          
}

さて、VisualDSP++3.5( February Update )が生成するコードを以下に示します。

このコードはベクトル同士の乗算同様に細かく場合分けされ、SIMD化されていますが、残念なことにループボディーの長さは人間が最適化する場合より1サイクル増えています。つまり、性能は半分しか出ていません。手で最適化すれば2191空挺団なぜ最適化できるかで説明した3段ソフトウェア・パイプライン化によってループ・ボディーを1サイクルに収めることができます。

        Dumping range 0xffa009fc - 0xffa00afb by 1 (Assembly)...
        [FFA009FC] P1 = R0 ;
        [FFA009FE] P0 = R1 ;
        [FFA00A00] [ -- SP ] = R7 ;
        [FFA00A02] R3 = [ SP + 0x10 ] ;
        [FFA00A04] CC = R3 <= 0 ;
        [FFA00A06] IF CC JUMP 114 /*0xFFA00A78*/ ;
        [FFA00A08] R0 = R0 | R1 ;
        [FFA00A0A] R7 = 3 ;
        [FFA00A0C] R0 = R0 & R7 ;
        [FFA00A0E] CC = R0 == 0 ;
        [FFA00A10] IF ! CC JUMP 76 /*0xFFA00A5C*/ ;
        [FFA00A12] CC = R3 <= 1 ;
        [FFA00A14] IF CC JUMP 62 /*0xFFA00A52*/ ;
        [FFA00A16] R0 = 1 ;
        [FFA00A18] R7 = R3 >>> 1 ;
        [FFA00A1C] R0 = MAX ( R0 , R7 ) ;
        [FFA00A20] R0 += -1 ;
        [FFA00A22] I0 = R1 ;
        [FFA00A24] P0 = R0 ;
        [FFA00A26] R2.H = R2.L << 0x0 ;
        [FFA00A2A] LSETUP ( 14 /*0xFFA00A38*/ , 22 /*0xFFA00A40*/ ) LC0 = P0 ;
        [FFA00A2E] CC = R0 == 0 ;
        [FFA00A30] R0 = [ I0 ++ ] ;
        [FFA00A32] IF CC JUMP 16 /*0xFFA00A42*/ ;
        [FFA00A34] NOP ;
        [FFA00A36] NOP ;
        [FFA00A38] R1.H = R0.H * R2.H , R1.L = R0.L * R2.L  || NOP  || R0 = [ I0 ++ ] ;
        [FFA00A40] [ P1 ++ ] = R1 ;
        [FFA00A42] R1.H = R0.H * R2.H , R1.L = R0.L * R2.L ;
        [FFA00A46] R0 = 1 ;
        [FFA00A48] R0 = R3 & R0 ;
        [FFA00A4A] CC = R0 == 1 ;
        [FFA00A4C] [ P1 ++ ] = R1 ;
        [FFA00A4E] P0 = I0 ;
        [FFA00A50] IF ! CC JUMP 40 /*0xFFA00A78*/ ( BP ) ;
        [FFA00A52] R0 = W [ P0 ++ ] ( X ) ;
        [FFA00A54] R0.L = R0.L * R2.L ;
        [FFA00A58] W [ P1 ++ ] = R0 ;
        [FFA00A5A] JUMP.S 30 /*0xFFA00A78*/ ;
        [FFA00A5C] R0 = 1 ;
        [FFA00A5E] R0 = MAX ( R0 , R3 ) ;
        [FFA00A62] P2 = R0 ;
        [FFA00A64] R0 = W [ P0 ++ ] ( X ) ;
        [FFA00A66] I0 = P1 ;
        [FFA00A68] LSETUP ( 4 /*0xFFA00A6C*/ , 8 /*0xFFA00A70*/ ) LC0 = P2 ;
        [FFA00A6C] R0.L = R0.L * R2.L ;
        [FFA00A70] MNOP  || R0 = W [ P0 ++ ] ( X )  || W [ I0 ++ ] = R0.L ;
        [FFA00A78] R7 = [ SP ++ ] ;
        [FFA00A7A] RTS ;

この辺はまだまだと思わせますが、どうでしょう。今回はベクトルとスカラーの積にそれほど性能を求めるわけではないので、このまま手を加えないで使っています。

Blackfin空挺団 | プログラム | EZ-KIT | コア&ペリフェラル | TOPPERS/JSP | こぼれ話 | DSP掲示板