2014-04-07 3 views
10

최근 Herb Sutter는 "Modern C++: What You Need to Know"에 대한 훌륭한 토론을했습니다. 이 강연의 주요 주제는 효율성과 데이터 지역성 및 메모리 액세스 방법에 관한 것입니다. 그는 또한 메모리의 선형 액세스 (배열/벡터)가 CPU에서 어떻게 사랑 받을지 설명했습니다. 그는이 주제에 대한 또 다른 고전적 참조 "Game performance by Bob Nystrom"에서 한 예를 취했습니다.C에서 명령어 캐시 친화적 인 프로그램을 작성하는 방법 + +?

  1. 데이터 캐시
  2. 명령 캐시

Cachegrind 도구는 모두 캐시 유형을 측정 :

이 기사를 읽은 후, 프로그램의 성능에 미치는 영향 캐시의 두 가지 유형이 있음을 얻었다 우리 프로그램의 기계 사용 정보. 첫 번째 사항은 많은 기사/블로그와 좋은 데이터 캐시 효율성 (데이터 지역성)을 달성하는 방법으로 설명되었습니다.

그러나 주제 에 대한 많은 정보를 얻지 못했습니다. 명령어 캐시 및 더 나은 성능을 얻기 위해 프로그램에서 어떤 조치를 취해야합니까? 내 이해에 따라, 우리 (프로그래머)는 어떤 명령이나 어떤 명령이 실행될 지에 대한 많은 통제를하지 못한다.

작은 C++ 프로그램이이 카운터 (.i.e 명령어 캐시)가 우리의 프로그램 작성 스타일에 따라 어떻게 달라진다면 정말 좋을 것입니다. 이 시점에서 더 나은 성능을 얻기 위해 프로그래머가 따라야 할 모범 사례는 무엇입니까?

우리 프로그램이 (vector vs list) 비슷한 방법으로 2 차 지점에 대해 설명 할 수 있다면 데이터 캐시 항목에 대해 이해할 수 있다는 것을 의미합니다. 이 질문의 주된 의도는 가능한 한이 주제를 이해하는 것입니다.

+1

가상 함수를 피하고 복잡한 코드를 작은 루프로 나누십시오. – lpapp

+1

@Leeor : 어떤면에서 복제본입니까? – lpapp

+0

죄송합니다. 잘못된 질문을 언급했습니다. 일단 컴퓨터 옆에 앉으면 투표를 철회 하겠지만 코드 캐시 컨텍스트 (예 : 추적 캐시, 디코딩 된 uop 캐시 등)를 사용하여 이전에 응답 한 것이 확실합니다. – Leeor

답변

8

실행 흐름을 변경하는 코드는 명령어 캐시에 영향을줍니다. 여기에는 함수 호출 및 루프뿐만 아니라 역 참조 함수 포인터가 포함됩니다.

분기 또는 점프 명령이 실행될 때 프로세서는 코드가 이미 명령 캐시에 있는지 또는 명령 캐시를 다시로드해야하는지 (지점의 대상에서) 여부를 결정해야합니다.

예를 들어 일부 프로세서에는 작은 루프에 대한 실행 코드를 저장하기에 충분한 명령 캐시가있을 수 있습니다. 일부 프로세서에는 큰 명령어 캐시가없고 간단하게 다시로드 할 수 있습니다. 명령 캐시를 다시로드하는 데는 지침을 실행하는 데 시간이 걸립니다.프로그래밍 기술 (ARM 프로세서에서 사용 가능)

  • 조건부 명령 실행
  • 인라인 함수
  • 명령 파이프 라인
  • 편집 일을 줄이기

    • 루프 :

      이 항목 검색 성능 향상을 위해
      성능을 개선하고 다음을 수행 명령어 캐시 다시로드 줄이려 :

      이 줄을 문 "만일"최소화하기 위해 코드를 디자인 문 "만일". 여기에는 부울 대수학 (Boolean Algebra)이 포함될 수 있으며 더 많은 수학을 사용하거나 비교를 단순화합니다 (실제로 필요합니까?). 컴파일러가 조건부 어셈블리 언어 명령어를 사용할 수 있도록 "then"및 "else"절의 내용을 줄이는 것이 좋습니다.

      는 복귀 위치를 저장하고, 명령 캐시를 다시로드와 같은 전화 기능과 관련된 오버 헤드가 작은 인라인로서 기능 또는 매크로
      정의. 소량의 명령문이있는 함수의 경우 컴파일러에 인라인으로 작성하도록 제안하십시오. 인라이닝은 함수 호출을 작성하는 대신 실행이있는 곳의 코드 내용을 붙여 넣는 것을 의미합니다. 함수 호출이 피하기 때문에 명령 캐시를 다시로드해야합니다.

      를 펴고 루프, 작은 반복 들어
      을하지 않는 루프,하지만 루프의 내용 (일부 컴파일러가 높은 최적화 수준 설정에서이 작업을 수행 할 수있다)를 반복합니다. 반복되는 내용이 많을수록 루프 맨 위로 분기되는 수가 적어지고 명령어 캐시를 다시로드 할 필요가 줄어 듭니다.

      를 사용하여 테이블을 조회하지
      일부 프로그램이 사용하는 "경우 - 다른-경우"매핑 데이터의 사다리 값으로 문 "만약". 각 "if"문은 명령 캐시에서의 실행 중단입니다. 때로는 약간의 수학을 사용하여 값을 배열과 같은 테이블에 배치하고 인덱스를 수학적으로 계산할 수 있습니다. 인덱스가 알려지면 프로세서는 명령 캐시를 방해하지 않고 데이터를 검색 할 수 있습니다. 데이터의 유형이 일정하면

      변경 데이터 또는 데이터 구조
      는, 프로그램 데이터의 주위에 최적화 될 수있다. 예를 들어, 메시지 패킷을 다루는 프로그램은 패킷 ID (함수 포인터의 배열을 생각해 보라)에 기반하여 연산을 기반으로 할 수있다. 함수는 패킷 처리를 위해 최적화됩니다.

      연결된 목록을 배열 또는 다른 임의 액세스 컨테이너로 변경하십시오. 배열 요소는 인터럽트 실행이 아닌 수학을 사용하여 액세스 할 수 있습니다. 링크 된 목록은 항목을 찾기 위해 탐색 (루프)되어야합니다.