2014-05-12 2 views
3

간단한 마이크로 벤치 마크를 사용하여 캐시 효과에 대해 공부하고 있습니다.

N이 캐시 크기보다 크면 캐시가 첫 번째 읽기 캐시 라인마다 누락 된 연산을한다고 생각합니다.

내 컴퓨터에서, 캐시 라인 크기 = 64Byte, 그래서 전적으로 캐시가 N/8 미스가 발생하고 캐시가 그라인드가 발생한다고 생각합니다.

그러나 perf 도구는 다른 결과를 표시합니다. 34,265 개의 캐시 미스 동작 만 발생합니다.

하드웨어 프리 페치가 의심 스럽기 때문에 BIOS에서이 기능을 해제하십시오. 어쨌든 결과는 같습니다.

perf tool의 캐시 누락이 "cachegrind"보다 작은 작업을하는 이유는 정말로 알지 못합니다. 누군가 나에게 합리적인 설명을 줄 수 있습니까?cachegrind 대 perf 도구 사이의 캐시 누락 횟수를 이해하지 못합니다.


1. 다음은 간단한 마이크로 벤치 마크 프로그램이다.

#> sudo perf stat -r 10 -e instructions -e cache-references -e cache-misses -e L1-dcache-loads -e L1-dcache-load-misses -e L1-dcache-stores -e L1-dcache-store-misses -e LLC-loads -e LLC-load-misses -e LLC-prefetches ./test 

    ==27612== Cachegrind, a cache and branch-prediction profiler 
    ==27612== Copyright (C) 2002-2013, and GNU GPL'd, by Nicholas Nethercote et al. 
    ==27612== Using Valgrind-3.9.0 and LibVEX; rerun with -h for copyright info 
    ==27612== Command: ./test 
    ==27612== 
    --27612-- warning: L3 cache found, using its data for the LL simulation. 
    ==27612== 
    ==27612== I refs:  110,102,998 
    ==27612== I1 misses:   728 
    ==27612== LLi misses:   720 
    ==27612== I1 miss rate:  0.00% 
    ==27612== LLi miss rate:  0.00% 
    ==27612== 
    ==27612== D refs:  70,038,455 (60,026,965 rd + 10,011,490 wr) 
    ==27612== D1 misses:  1,251,802 (1,251,288 rd +  514 wr) 
    ==27612== LLd misses:  1,251,624 (1,251,137 rd +  487 wr) 
    ==27612== D1 miss rate:   1.7% (  2.0%  +  0.0% ) 
    ==27612== LLd miss rate:   1.7% (  2.0%  +  0.0% ) 
    ==27612== 
    ==27612== LL refs:   1,252,530 (1,252,016 rd +  514 wr) 
    ==27612== LL misses:  1,252,344 (1,251,857 rd +  487 wr) 
    ==27612== LL miss rate:   0.6% (  0.7%  +  0.0% ) 

    Generate a report File 
    -------------------------------------------------------------------------------- 
    I1 cache:   32768 B, 64 B, 4-way associative 
    D1 cache:   32768 B, 64 B, 8-way associative 
    LL cache:   8388608 B, 64 B, 16-way associative 
    Command:   ./test 
    Data file:  cache_block 
    Events recorded: Ir I1mr ILmr Dr D1mr DLmr Dw D1mw DLmw 
    Events shown:  Ir I1mr ILmr Dr D1mr DLmr Dw D1mw DLmw 
    Event sort order: Ir I1mr ILmr Dr D1mr DLmr Dw D1mw DLmw 
    Thresholds:  0.1 100 100 100 100 100 100 100 100 
    Include dirs:  
    User annotated: /home/jin/1_dev/99_test/OI/test.s 
    Auto-annotation: off 

-------------------------------------------------------------------------------- 
     Ir I1mr ILmr   Dr  D1mr  DLmr   Dw D1mw DLmw 
-------------------------------------------------------------------------------- 
110,102,998 728 720 60,026,965 1,251,288 1,251,137 10,011,490 514 487 PROGRAM TOTALS 

-------------------------------------------------------------------------------- 
     Ir I1mr ILmr   Dr  D1mr  DLmr   Dw D1mw DLmw   file:function 
-------------------------------------------------------------------------------- 
110,000,011 1 1 60,000,003 1,250,000 1,250,000 10,000,003 0 0 /home/jin/1_dev/99_test/OI/test.s:main 

-------------------------------------------------------------------------------- 
-- User-annotated source: /home/jin/1_dev/99_test/OI/test.s 
-------------------------------------------------------------------------------- 
     Ir I1mr ILmr   Dr  D1mr  DLmr   Dw D1mw DLmw 

-- line 2 ---------------------------------------- 
     . . .   .   .   .   . . .   .comm A,80000000,32 
     . . .   .   .   .   . . . .comm B,80000000,32 
     . . .   .   .   .   . . . .text 
     . . .   .   .   .   . . . .globl main 
     . . .   .   .   .   . . . .type main, @function 
     . . .   .   .   .   . . . main: 
     . . .   .   .   .   . . . .LFB0: 
     . . .   .   .   .   . . . .cfi_startproc 
     1 0 0   0   0   0   1 0 0 pushq %rbp 
     . . .   .   .   .   . . . .cfi_def_cfa_offset 16 
     . . .   .   .   .   . . . .cfi_offset 6, -16 
     1 0 0   0   0   0   0 0 0 movq %rsp, %rbp 
     . . .   .   .   .   . . . .cfi_def_cfa_register 6 
     1 0 0   0   0   0   0 0 0 movl $0, %eax 
     1 1 1   0   0   0   1 0 0 movq %rax, -16(%rbp) 
     1 0 0   0   0   0   1 0 0 movl $0, -4(%rbp) 
     1 0 0   0   0   0   0 0 0 jmp .L2 
     . . .   .   .   .   . . . .L3: 
10,000,000 0 0 10,000,000   0   0   0 0 0 movl -4(%rbp), %eax 
10,000,000 0 0   0   0   0   0 0 0 cltq 
10,000,000 0 0 10,000,000 1,250,000 1,250,000   0 0 0 movsd A(,%rax,8), %xmm1 
10,000,000 0 0 10,000,000   0   0   0 0 0 movl -4(%rbp), %eax 
10,000,000 0 0   0   0   0   0 0 0 cltq 
10,000,000 0 0 10,000,000   0   0   0 0 0 movsd A(,%rax,8), %xmm0 
10,000,000 0 0   0   0   0   0 0 0 mulsd %xmm1, %xmm0 
10,000,000 0 0   0   0   0 10,000,000 0 0 movsd %xmm0, -16(%rbp) 
10,000,000 0 0 10,000,000   0   0   0 0 0 addl $1, -4(%rbp) 
     . . .   .   .   .   . . . .L2: 
10,000,001 0 0 10,000,001   0   0   0 0 0 cmpl $9999999, -4(%rbp) 
10,000,001 0 0   0   0   0   0 0 0 jle .L3 
     1 0 0   0   0   0   0 0 0 movl $0, %eax 
     1 0 0   1   0   0   0 0 0 popq %rbp 
     . . .   .   .   .   . . . .cfi_def_cfa 7, 8 
     1 0 0   1   0   0   0 0 0 ret 
     . . .   .   .   .   . . . .cfi_endproc 
     . . .   .   .   .   . . . .LFE0: 
     . . .   .   .   .   . . . .size main, .-main 
     . . .   .   .   .   . . . .ident "GCC: (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3" 
     . . .   .   .   .   . . . .section .note.GNU-stack,"",@progbits 

-------------------------------------------------------------------------------- 
Ir I1mr ILmr Dr D1mr DLmr Dw D1mw DLmw 
-------------------------------------------------------------------------------- 
100 0 0 100 100 100 100 0 0 percentage of events annotated 


3. 다음과 같은 결과가의 PERF되어 출력 : 대한

성능 카운터 통계 '결과에 따라

#include <stdio.h> 
    #define N 10000000 

    double A[N]; 

    int main(){ 

    int i; 
    double temp=0.0; 

    for (i=0 ; i<N ; i++){ 
     temp = A[i]*A[i]; 
    } 

    return 0; 
} 


2 cachegrind의 출력됩니다./test '(10 회) :

113,898,951 instructions    # 0.00 insns per cycle   (+- 12.73%) [17.36%] 
     53,607 cache-references            (+- 12.92%) [29.23%] 
     1,483 cache-misses    # 2.767 % of all cache refs  (+- 26.66%) [39.84%] 
    48,612,823 L1-dcache-loads            (+- 4.58%) [50.45%] 
     34,256 L1-dcache-load-misses  # 0.07% of all L1-dcache hits (+- 18.94%) [54.38%] 
    14,992,686 L1-dcache-stores            (+- 4.90%) [52.58%] 
     1,980 L1-dcache-store-misses          (+- 6.36%) [61.83%] 
     1,154 LLC-loads              (+- 61.14%) [53.22%] 
      18 LLC-load-misses   # 1.60% of all LL-cache hits  (+- 16.26%) [10.87%] 
      0 LLC-prefetches            [ 0.00%] 

    0.037949840 seconds time elapsed           (+- 3.57%) 




실험적인 결과 (2014년 5월 13일)

[email protected]:~/1_dev/99_test/OI$ sudo perf stat -r 10 -e instructions -e r53024e -e r53014e -e L1-dcache-loads -e L1-dcache-load-misses -e r500f0a -e r500109 ./test 

Performance counter stats for './test' (10 runs): 

    116,464,390 instructions    # 0.00 insns per cycle   (+- 2.67%) [67.43%] 
     5,994 r53024e <-- L1D hardware prefetch misses      (+- 21.74%) [70.92%] 
    1,387,214 r53014e <-- L1D hardware prefetch requests     (+- 2.37%) [75.61%] 
    61,667,802 L1-dcache-loads            (+- 1.27%) [78.12%] 
     26,297 L1-dcache-load-misses  # 0.04% of all L1-dcache hits (+- 48.92%) [43.24%] 
      0 r500f0a <-- LLC lines allocated         [56.71%] 
     41,545 r500109 <-- Number of LLC read misses      (+- 6.16%) [50.08%] 

    0.037080925 seconds time elapsed  
상기 결과에서


는 "L1D 하드웨어 프리 페치 요청"의 수가 D1 미스 같아 (125).


결론적으로 메모리가 "스트림 패턴"에 액세스하면 L1D 프리 페치 기능이 활성화됩니다. LLC miss 정보로 인해 메모리에서 얼마나 많은 바이트로드가되는지 확인할 수 없습니다.

내 결론이 맞습니까?

+0

사용했던 명령 줄을 추가 할 수 있습니까? gcc 옵션, perf stat ... – amigadev

+0

늦게 답변드립니다. 명령 행은 다음과 같습니다 : #> sudo perf stat -r 10 -e 명령 -e cache-references -e cache-misses -e L1-dcache -load -e L1-dcache-load-misses -e L1-dcache-stores - e L1-dcache-store-misses -e LLC-loads -e LLC-load-misses -e LLC-prefetches ./test – libertyjin

+1

초기 프로그램이 컴파일러에 의해 최적화되지 않았습니까? 특히 A [i] * A [i]가 반복 사이에 저장되지 않기 때문에 주 루프를 우회 할 수 있습니다 (이중 배열을 임시로 사용하는 경우 문제가 해결됨). 필자는 컴파일러가 마이크로 벤치 마크를 최적화하고 있다고 생각합니다. –

답변

1

하단 라인 : 프리 페치에 대한 가정은 정확하지만 해결 방법은 올바르지 않습니다.

먼저 Carlo가 지적했듯이이 루프는 일반적으로 모든 컴파일러에서 최적화됩니다. perf와 cachegrind 모두 ~ 100M 명령어가 은퇴했음을 보여주기 때문에 최적화로 컴파일하지 않았을 것입니다. 즉, 동작이 매우 현실적이지 않음을 의미합니다. 예를 들어, 루프 변수가 레지스터 대신 메모리에 저장 될 수 있습니다. 무의미한 메모리 액세스 및 비뚤어 짐 캐시 카운터.

지금, 당신의 실행의 차이는 cachgrind 그냥 캐시 시뮬레이터입니다, 그것은 예상대로 그렇게 한 줄에 모든 처음 액세스가 그리워, 프리 페치을 시뮬레이션하지 않습니다.반면, 실제 CPU는 사용자가 볼 수있는 것처럼 HW 프리 페치를 가지고 있으므로 처음으로 각 라인이 메모리에서 가져와지면 실제 요구로드가 아니라 미리 읽기 (간단한 스트리밍 패턴 덕분에)가 완료됩니다. 이것이 perf가 정상 카운터로 이러한 액세스를 계산하지 못하는 이유입니다.

프리 페치 카운터를 활성화하면 대략 동일한 N/8 프리 페치 (다른 유형의 액세스로부터의 추가 페어가있을 가능성이 높음)를 볼 수 있습니다.

프리 페처를 사용하지 않도록 설정하는 것이 옳은 것처럼 보일 수 있지만 대부분의 CPU는이를 제어하지 못합니다. 사용중인 프로세서 유형은 지정하지 않았지만 예를 들어 Intel 인 경우 BIOS에서 L2 프리 페치 만 제어하고 출력은 L1 프리 페치를 보여줍니다. https://software.intel.com/en-us/articles/optimizing-application-performance-on-intel-coret-microarchitecture-using-hardware-implemented-prefetchers

검색 CPU 유형에 대한 매뉴얼은 L1 프리 페처가 있는지 확인하고이를 해결하는 방법을 이해합니다. 일반적으로 간단한 스트라이드 (단일 캐시 라인보다 큼)로 트릭을 수행 할 수 있지만 작동하지 않는 경우 액세스 패턴을보다 무작위로 변경해야합니다. 당신은 그 색인의 일부 순열을 무작위로 나타낼 수 있습니다.

관련 문제