chroot("/home/hibari")

備忘録とかに使えそうなノート

PowerPCのアライメントについて

前記事でPowerPCにおける条件分岐について簡単な実験を行ったが,もう一点つい気になってしまったことがある.アライメントのことである.PowerPCであろうとx86であろうと,アライメントは揃えるのは当然な話である.

PowerPCRISCであり32-bitの場合4byteで固定されている.そのため「4byte」がキモなのかと思った.

実験としてはこれまた非常にシンプルで,4byteアライメントされているアクセスをひたすらするような関数と,アライメントされていないアクセスをひたすらするような関数の2つを用意して実行時間を計測した.

 

この実験を行うためのアセンブリプログラムは以下の通りである.行列の和を求めるシンプルな関数である.今回は1024x1024の行列の和を想定している.

add_matrix_aligned:
    li      0, 1024
    mulli   15, 0, 4
    mullw   16, 15, 0
    li      8, 0

add_outer_aligned:
    li      9, 0
    mtctr   0

add_inner_aligned:
    add     10, 3, 8
    add     11, 4, 8
    lwzx    13, 10, 9
    lwzx    14, 11, 9
    add     13, 13, 14
    add     12, 5, 8
    stwx    13, 12, 9
    addi    9, 9, 4
    bdnz+   add_inner_aligned

    add     8, 8, 15
    cmpw    7, 8, 16
    bne     7, add_outer_aligned
    blr

 

アライメントされていない場合の関数に関しては"li  9, 0"の部分を"li  9, 2"として常に4+2のアドレスにアクセスするようにした.

このプログラムを100回ループした時の実行時間は以下の通りになった.alignedがアライメントされている方で,badがされていない方である.

$ ./add_matrix

add_matrix_aligned : 4.759800 [s]

add_matrix_bad : 5.624340 [s]

一目でわかるレベルにアライメントされていない方が実行時間が遅くなっていることが確認できた.

 

 

よりみち

行列和のアセンブリプログラムを書きながら,もうちょっとコードの長さを短く出来ないかなあと思ってついそのまま作ってみた.1024x1024の行列の和を想定しているから出来るコードではあるが,実行時間に変化があるかなと気になった.以下の通りである.

add_matrix_comp:
    li      0, 1024
    mullw   0, 0, 0
    mtctr   0
    li      8, 0

comp_loop:
    lwzx    10, 3, 8
    lwzx    11, 4, 8
    add     10, 10, 11
    stwx    10, 5, 8
    addi    8, 8, 4
    bdnz+   comp_loop

    blr

 

命令数が19から11に減った.そしてそのまま実行してみた.add_matrix_compが上のコードである.

$ ./add_matrix

add_matrix_comp : 4.617402 [s]

add_matrix_aligned : 4.759102 [s]

add_matrix_bad : 5.638711 [s]

 

結局メモリ律速なプログラムではあるが,素直な実装よりも少しだけ速くなった.