ぺんぎんさんのおうち

日記です。たまに日記じゃないこともあります。

03.06.2020

10時起床.前日比±0

 

 

配列の中身をコピーする方法をいくつか試したら,実行時間が若干変わったのが気になった.

Mad521の修正 · ykm11/lab-youth@a41fa77 · GitHub

for文を使ってのコピーは賢くないな.

 

次のようなコードを書いてみる.実行環境はUbuntu, gcc 9.3.0

void f(mp_limb_t *a, const mp_limb_t *b) {
    memcpy(a, b, sizeof(mp_limb_t) * 9);
}

 

void g(mp_limb_t *a, const mp_limb_t *b) {
    memcpy(a, b, sizeof(mp_limb_t) * 8);
    a[8] = b[8];
}

-O3でコンパイルすると同じアセンブリが出てくる(のでどちらが良い, 速いとかはない).

movdqu xmm0,XMMWORD PTR [rsi] 

movdqu xmm0,XMMWORD PTR [rsi]

movups XMMWORD PTR [rdi],xmm0 

movdqu xmm1,XMMWORD PTR [rsi+0x10] 

movups XMMWORD PTR [rdi+0x10],xmm1 

movdqu xmm2,XMMWORD PTR [rsi+0x20] 

movups XMMWORD PTR [rdi+0x20],xmm2 

movdqu xmm3,XMMWORD PTR [rsi+0x30] 

movups XMMWORD PTR [rdi+0x30],xmm3 

mov    rax,QWORD PTR [rsi+0x40] 

mov    QWORD PTR [rdi+0x40],rax 

ret 

nop    DWORD PTR [rax+rax*1+0x0]

mp_limb_tが64ビット(x86なら32)なので,128ビットのレジスタを4つとraxを使ってコピーしている.memcpyを呼び出すまでもないらしい.

 

memcpyの第三引数に定数を渡してあると,たとえばmemcpy(x, y, 2434)のように書くと128ビットレジスタを上手いこと駆使してmemcpyを呼び出さないようにしていた.memcpy(x, y, 0x2434)だとさすがにjmp memcpy@pltしてた.0x2000以下だとmemcpy使わないんだね.

 

第三引数が定数 かつ 0x2000以下

-> memcpyを呼ばない

第三引数が変数 または 0x2001以上

-> memcpyを呼ぶ

 

clangではどうなるのかわからないので誰か試してほしい.