2016-03-21 17 views
2

私は、Intelマシン上での読み書きアクセスに対して非常に奇妙なパフォーマンスを観察しています。x86での書き込みは、読み込みより高速ですか?

まず、配列を割り当てるCプログラムを作成しました。プログラムのコードは[1]にあります。 Makeを実行するとコンパイルできます。 (私は任意のコンパイルの最適化を使用していない)

を次のようにプログラムの動作の順序は次のとおりです。

allocate a char array; 
init each element of array to be 1; 
use clflush to flush the whole array from cache; 
read each cache line of the array by using tmp = array[i]; 
(Do simple calculation after reading each cache line) 
use clflush to flush the whole array from cache; 
write each cache line of the array by using array[i] = tmp; 
(Do the same simple calculation after reading each cache line) 

私は、インテル(R)Xeon(R)CPU上でプログラムを実行しますE5-ターボブーストが無効の1650 v2 @ 3.50GHz(ハスウェルアーチ)。

私はプログラムを実行するために使用するコマンドは、次のとおりです。./rw-latency-test-compute sudoの私は全体のアレイの読み出しレイテンシは、6670usで得た10 1

5210しばらくの間、書き込みレイテンシ配列全体は3518usです。

興味深い部分は、私が読んだ後、私はすべての計算を行わない場合は/キャッシュラインを書き ある配列全体の書き込みレイテンシは3687usありながら、全体のアレイの読み出しレイテンシは、2175usです。だから、計算をやって

が実行をスピードアップするようだ... :-(

あなたはこの奇妙なパフォーマンス上の任意の提案/説明を持っていますか?

プログラムの全体のアセンブリコードはで見つけることができます[ 2]

次のように内側ループのアセンブリコードである:。

0000000000400898 <read_array>: 
    400898: 55      push %rbp 
    400899: 48 89 e5    mov %rsp,%rbp 
    40089c: 53      push %rbx 
    40089d: 48 83 ec 28    sub $0x28,%rsp 
    4008a1: 48 89 7d d8    mov %rdi,-0x28(%rbp) 
    4008a5: 48 89 75 d0    mov %rsi,-0x30(%rbp) 
    4008a9: c7 45 e8 00 00 00 00 movl $0x0,-0x18(%rbp) 
    4008b0: c7 45 e4 00 00 00 00 movl $0x0,-0x1c(%rbp) 
    4008b7: eb 58     jmp 400911 <read_array+0x79> 
    4008b9: b8 00 00 00 00   mov $0x0,%eax 
    4008be: e8 38 ff ff ff   callq 4007fb <sw_barrier> 
    4008c3: 8b 45 e4    mov -0x1c(%rbp),%eax 
    4008c6: 48 98     cltq 
    4008c8: 48 03 45 d8    add -0x28(%rbp),%rax 
    4008cc: 0f b6 00    movzbl (%rax),%eax 
    4008cf: 88 45 ef    mov %al,-0x11(%rbp) 
    4008d2: 0f be 45 ef    movsbl -0x11(%rbp),%eax 
    4008d6: 89 c1     mov %eax,%ecx 
    4008d8: 03 4d e8    add -0x18(%rbp),%ecx 
    4008db: ba 01 80 00 80   mov $0x80008001,%edx 
    4008e0: 89 c8     mov %ecx,%eax 
    4008e2: f7 ea     imul %edx 
    4008e4: 8d 04 0a    lea (%rdx,%rcx,1),%eax 
    4008e7: 89 c2     mov %eax,%edx 
    4008e9: c1 fa 0f    sar $0xf,%edx 
    4008ec: 89 c8     mov %ecx,%eax 
    4008ee: c1 f8 1f    sar $0x1f,%eax 
    4008f1: 89 d3     mov %edx,%ebx 
    4008f3: 29 c3     sub %eax,%ebx 
    4008f5: 89 d8     mov %ebx,%eax 
    4008f7: 89 45 e8    mov %eax,-0x18(%rbp) 
    4008fa: 8b 55 e8    mov -0x18(%rbp),%edx 
    4008fd: 89 d0     mov %edx,%eax 
    4008ff: c1 e0 10    shl $0x10,%eax 
    400902: 29 d0     sub %edx,%eax 
    400904: 89 ca     mov %ecx,%edx 
    400906: 29 c2     sub %eax,%edx 
    400908: 89 d0     mov %edx,%eax 
    40090a: 89 45 e8    mov %eax,-0x18(%rbp) 
    40090d: 83 45 e4 40    addl $0x40,-0x1c(%rbp) 
    400911: 8b 45 e4    mov -0x1c(%rbp),%eax 
    400914: 48 98     cltq 
    400916: 48 3b 45 d0    cmp -0x30(%rbp),%rax 
    40091a: 7c 9d     jl  4008b9 <read_array+0x21> 
    40091c: b8 e1 0f 40 00   mov $0x400fe1,%eax 
    400921: 8b 55 e8    mov -0x18(%rbp),%edx 
    400924: 89 d6     mov %edx,%esi 
    400926: 48 89 c7    mov %rax,%rdi 
    400929: b8 00 00 00 00   mov $0x0,%eax 
    40092e: e8 3d fd ff ff   callq 400670 <[email protected]> 
    400933: 48 83 c4 28    add $0x28,%rsp 
    400937: 5b      pop %rbx 
    400938: 5d      pop %rbp 
    400939: c3      retq 

000000000040093a <write_array>: 
    40093a: 55      push %rbp 
    40093b: 48 89 e5    mov %rsp,%rbp 
    40093e: 53      push %rbx 
    40093f: 48 83 ec 28    sub $0x28,%rsp 
    400943: 48 89 7d d8    mov %rdi,-0x28(%rbp) 
    400947: 48 89 75 d0    mov %rsi,-0x30(%rbp) 
    40094b: c6 45 ef 01    movb $0x1,-0x11(%rbp) 
    40094f: c7 45 e8 00 00 00 00 movl $0x0,-0x18(%rbp) 
    400956: c7 45 e4 00 00 00 00 movl $0x0,-0x1c(%rbp) 
    40095d: eb 63     jmp 4009c2 <write_array+0x88> 
    40095f: b8 00 00 00 00   mov $0x0,%eax 
    400964: e8 92 fe ff ff   callq 4007fb <sw_barrier> 
    400969: 8b 45 e4    mov -0x1c(%rbp),%eax 
    40096c: 48 98     cltq 
    40096e: 48 03 45 d8    add -0x28(%rbp),%rax 
    400972: 0f b6 55 ef    movzbl -0x11(%rbp),%edx 
    400976: 88 10     mov %dl,(%rax) 
    400978: 8b 45 e4    mov -0x1c(%rbp),%eax 
    40097b: 48 98     cltq 
    40097d: 48 03 45 d8    add -0x28(%rbp),%rax 
    400981: 0f b6 00    movzbl (%rax),%eax 
    400984: 0f be c0    movsbl %al,%eax 
    400987: 89 c1     mov %eax,%ecx 
    400989: 03 4d e8    add -0x18(%rbp),%ecx 
    40098c: ba 01 80 00 80   mov $0x80008001,%edx 
    400991: 89 c8     mov %ecx,%eax 
    400993: f7 ea     imul %edx 
    400995: 8d 04 0a    lea (%rdx,%rcx,1),%eax 
    400998: 89 c2     mov %eax,%edx 
    40099a: c1 fa 0f    sar $0xf,%edx 
    40099d: 89 c8     mov %ecx,%eax 
    40099f: c1 f8 1f    sar $0x1f,%eax 
    4009a2: 89 d3     mov %edx,%ebx 
    4009a4: 29 c3     sub %eax,%ebx 
    4009a6: 89 d8     mov %ebx,%eax 
    4009a8: 89 45 e8    mov %eax,-0x18(%rbp) 
    4009ab: 8b 55 e8    mov -0x18(%rbp),%edx 
    4009ae: 89 d0     mov %edx,%eax 
    4009b0: c1 e0 10    shl $0x10,%eax 
    4009b3: 29 d0     sub %edx,%eax 
    4009b5: 89 ca     mov %ecx,%edx 
    4009b7: 29 c2     sub %eax,%edx 
    4009b9: 89 d0     mov %edx,%eax 
    4009bb: 89 45 e8    mov %eax,-0x18(%rbp) 
    4009be: 83 45 e4 40    addl $0x40,-0x1c(%rbp) 
    4009c2: 8b 45 e4    mov -0x1c(%rbp),%eax 
    4009c5: 48 98     cltq 
    4009c7: 48 3b 45 d0    cmp -0x30(%rbp),%rax 
    4009cb: 7c 92     jl  40095f <write_array+0x25> 
    4009cd: b8 ee 0f 40 00   mov $0x400fee,%eax 
    4009d2: 8b 55 e8    mov -0x18(%rbp),%edx 
    4009d5: 89 d6     mov %edx,%esi 
    4009d7: 48 89 c7    mov %rax,%rdi 
    4009da: b8 00 00 00 00   mov $0x0,%eax 
    4009df: e8 8c fc ff ff   callq 400670 <[email protected]> 
    4009e4: 48 83 c4 28    add $0x28,%rsp 
    4009e8: 5b      pop %rbx 
    4009e9: 5d      pop %rbp 
    4009ea: c3      retq 

[1] https://github.com/PennPanda/rw-latency-test/blob/master/rw-latency-test-compute.c

[2] https://github.com/PennPanda/rw-latency-test/blob/2da88f1cccba40aba155317567199028b28bd250/rw-latency-test-compute.asm

+0

あなたは明確な回答のための十分な情報を投稿していませんが、私はあなたの書き込みがおそらく純粋なシンクであることを指摘しています。つまり、簡単にバッファリングできます。対照的に、読み込みはプログラムに依存関係があることを意味します。 – EOF

+0

@ EOF、他に必要な情報をお知らせください。私はここに全体のプログラムを投稿していませんでしたが、それほど厄介ではないようにgithubに入れてください... – Mike

+1

あなたはx86について具体的に質問しているので、私はアセンブリコードを見てみたいと思います。あなたのテストケースの内部ループ。また、あなたのタイミングは疑わしいほど多くの有効数字を持っています。あなたはどのくらいの時間を過ごしましたか、どのような平均値、中央値の結果を得ましたか、どのような分散? – EOF

答えて

4

書き込みは、あなたがRAMから読み込まれた値を使用している場合(つまり、あなただけ読んで、破棄しない)ので、読んでより高速で、プロセッサはで、読み取りのために失速しています値が使用されていることを示します。しかし、書き込みは非同期的に進み、決してストールしません。

+0

にありますが、まずキャッシュをフラッシュします。つまり、配列アイテムを書き込むと、インテル(書き込み割り当て)キャッシュは最初に(キャッシュにロードすることによって)アイテムのキャッシュラインを割り当ててからキャッシュに書き込みます。さらに、計算では、tmp値の代わりに配列の結果が使用されます。つまり、IMHOの場合は、配列の値の準備が完了するまで待つ必要があります。ではない? – Mike

+2

@MikeXu:ストアロードフォワーディングを参照してください。これはまさにあなたの 'write_array()'で起こっていることです。 – EOF

+0

@ EOF、私はストアロードフォワーディングを取得しました。あなたの提案をありがとう!私は簡単な質問をしてもいいですか? write_array()に、Cソースコードまたはアセンブリコードからストアロード転送の問題があるとどのように伝えましたか? – Mike

関連する問題