CPU 캐시를 최적화 할 때 무엇이 ​​중요합니까 (C)?


13

두 가지 질문을 읽으면 메모리에서 많은 양의 데이터를 처리 할 때 CPU 캐싱 동작을 이해하는 것이 중요 할 수 있습니다. 캐싱이 작동하여 최적화 도구 상자에 다른 도구를 추가하는 방법을 알고 싶습니다.

CPU 캐시가 작동하는 방식에 대한 핵심 요점은 무엇입니까? 그래서 그것을 현명하게 사용하는 코드를 작성할 수 있습니까? 관련하여, 캐시 사용이 불량한지 확인하기 위해 코드를 프로파일 링하는 방법이 있습니까?


캐시는 어디에서나 동일하지 않습니다. 가장 분명하게는 크기가 다양합니다. Michael Borgwardt의 조언과 같은 모범 사례만으로도 깊은 비밀을 배울 것으로 기대하지 마십시오.
David Thornley

답변:


17
  • 가능하면 데이터를 작게 유지하십시오
  • 서로 접근 할 수있는 것들 (또는 서로 바로 뒤)을 메모리에 보관하십시오.
  • 컴파일러의 최적화 매개 변수에 대해 학습
  • 당신이 원했던 것보다 자세한 내용 은 모든 프로그래머가 메모리대해 알아야 할 내용을 읽으십시오

"서로 접근 할 수있는 것들을 지키십시오"+1; 그것은 잊기 쉬운 것입니다.
Donal Fellows

그리고 컴파일러에게 최적화하도록 지시하십시오.
rightfold December

@WTP : 오른쪽-추가되었습니다.
Michael Borgwardt

또한 뮤텍스를 잘 분리하십시오. 뮤텍스 (변경해야 함)를 변경하면 모든 CPU에서 캐시 라인이 모두 플러시됩니다. 단일 캐시 라인에서 2-3 개의 뮤텍스를 얻을 수 있다면 성능에 큰 타격을 줄 수 있습니다.
Vatine

12

요즘이 문제의 복잡성은 인간의 이해를 넘어서고있다. (지난 5 년 이후 그렇게되었습니다.)이를 SIMD (Short-Vector Parallelism)와 결합하면 손으로 코드를 최적화하는 것이 더 이상 경제적으로 실현 가능하지 않다는 소망이 있습니다. 더 이상 비용 효율적이지 않습니다.

현재 접근 방식은 서로 다른 구조 (루프, 데이터 구조, 알고리즘)로 동일한 답변을 계산하는 코드 변형을 만들고 성능을 자동으로 평가하여 컴퓨터를 최적화하는 방법에 의존하는 것입니다. 코드 변환 규칙은 매우 엄격한 수학적 모델로 지정되므로 컴퓨터 과학자가 이해할 수 있고 컴퓨터가 실행할 수 있습니다.

다음은 Larry OBrien 이 그의 답변 중 하나에 게시 한 링크 입니다.

http://onward-conference.org/2011/images/Pueschel_2011_AutomaticPerformanceProgramming_Onward11.pdf


2
fasttest의 BLAS 구현 (GotoBLAS)는 최대 캐시 행렬 곱셈에 대한 사용하기 위해 손으로 최적화 된 코드를 사용
quant_dev

2

캐시를 이해하고 최적화하는 것이 가능합니다. 하드웨어 이해부터 시작하여 시스템을 제어합니다. 시스템에 대한 통제력이 낮을수록 성공할 가능성이 줄어 듭니다. 유휴 상태가 아닌 많은 응용 프로그램 / 스레드를 실행하는 Linux 또는 Windows

대부분의 캐시는 속성이 다소 유사하며 주소 필드의 일부를 사용하여 적중을 찾고 깊이 (길이) 및 너비 (캐시 라인)를 갖습니다. 일부에는 쓰기 버퍼가 있으며 일부는 쓰기시 캐시를 쓰거나 우회하도록 구성 할 수 있습니다.

해당 캐시에 도달하는 모든 메모리 트랜잭션에 대해 잘 알고 있어야합니다 (일부 시스템에는 독립적 인 명령 및 데이터 캐시가있어 작업을보다 쉽게 ​​수행 할 수 있음).

메모리를 신중하게 관리하지 않으면 캐시를 쉽게 쓸모 없게 만들 수 있습니다. 예를 들어, 처리중인 데이터 블록이 여러 개인 경우 캐시에 보관하기를 원하지만 캐시 적중 / 미스 확인에 비해 배수가 많은 주소의 메모리에 있습니다 (예 : 0x10000 0x20000 0x30000). 캐시의 방식보다 캐시를 ​​껐을 때보 다 느리게 실행되는 항목을 매우 빠르게 만들 수 있습니다. 그러나이를 0x10000, 0x21000, 0x32000으로 변경하면 캐시를 최대한 활용하여 제거를 줄일 수 있습니다.

결론적으로, 캐시를 최적화하는 핵심은 (시스템을 잘 아는 것 이외의) 캐시에서 성능에 필요한 모든 것을 동시에 캐시에 보관하여 가능한 한 데이터를 구성하는 것입니다. 캐시에 모두 한 번에. 또한 코드 실행, 인터럽트 및 기타 정기 또는 임의의 이벤트와 같은 것들이 사용중인이 데이터의 상당 부분을 제거하지 못하게합니다.

코드도 마찬가지입니다. 캐시에 유지하려는 다른 코드와의 충돌을 피하기 위해 코드가있는 위치를 제어해야하기 때문에 조금 더 어렵습니다. 여기에 코드 한 줄을 추가하거나 캐시를 통과하는 코드를 테스트 / 프로파일 링하는 동안 또는 동일한 코드에 대해 한 컴파일에서 다른 컴파일로 코드가있는 주소를 변경하거나 변경하는 경우 위치가 변경됩니다. 캐시 라인은 해당 코드에 속하며 제거되는 항목과 중요한 섹션에없는 항목을 변경합니다.


1

nwongMichael Borgwardt의 답변 모두 좋은 조언을 제공합니다.

또한 이러한 문제에 대한 컴파일러의 최적화를 먼저 신뢰하십시오.

최근 GCC 컴파일러를 사용하는 경우 parsimony와 함께 해당 __builtin_prefetch기능을 사용할 수 있습니다 . stackoverflow 에서이 답변 을 참조하십시오 .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.