문제

에서 32 비트 CPU,정수는 4 바이트 및 짧은 정수는 2 바이트입니다.내가 쓰는 C/C++응용 프로그램을 사용하는 많은 숫자 값이 항상 내에 제공한 범위의 정수,그것은 더 효율적으로 사용하는 4 바이트 정수 또는 2 바이트 정수가?

나는 그것을 들었을 제안하는 4 바이트 정수를 더 효율적으로 이에 맞는 대역폭의 메모리에서 버스에게 CPU.그러나,경우 추가 함께 두 개의 짧은 정수,을 것입 CPU 패키지 모두의 값을 하나의 패스에서 병렬로(따라서 걸친 4 바이트로의 대역폭 버스)?

도움이 되었습니까?

해결책

예, 32 비트 CPU에서 32 비트 정수를 사용해야합니다. 그렇지 않으면 사용되지 않은 비트를 마스킹하게 될 수 있습니다 (즉, 항상 32 비트로 수학을 수행 한 다음 답을 16 비트로 변환합니다).

그것은 당신을 위해 한 번에 두 개의 16 비트 작업을 수행하지는 않지만, 코드를 직접 작성하고 오버플로되지 않을 것이라고 확신하면 직접 할 수 있습니다.

편집하다: 나는 또한 "효율적인"정의에 다소 의존한다고 덧붙여 야합니다. 32 비트 작업을 더 빨리 수행 할 수는 있지만 물론 두 배의 메모리를 사용할 것입니다.

내부 루프 어딘가에서 중간 계산에 사용되는 경우 32 비트를 사용하십시오. 그러나 디스크에서 이것을 읽거나 캐시 미스 비용을 지불 해야하는 경우 16 비트 정수를 사용하는 것이 여전히 더 잘 작동 할 수 있습니다. 모든 최적화와 마찬가지로 알아야 할 방법은 다음과 같습니다. 프로파일.

다른 팁

많은 숫자 배열이 있다면 가장 작은 크기로 이동하십시오. 캐시 밀도의 두 배를 얻기 때문에 32 비트 int보다 16 비트 반바지 배열로 작업하는 것이 더 효율적입니다. CPU가 32 비트 레지스터에서 16 비트 값으로 작동하기 위해 수행 해야하는 모든 부호 확장 비용은 캐시 미스 비용에 비해 매우 무시할 수 있습니다.

다른 데이터 유형과 혼합 된 클래스에서 멤버 변수를 단순히 사용하는 경우 패딩 요구 사항이 16 비트 값의 공간 절약 혜택을 제거 할 수 있으므로 명확하지 않습니다.

"많은"정수 값을 사용하는 경우 처리의 병목 현상은 메모리에 대역폭이 될 수 있습니다. 16 비트 정수는 데이터 캐시에 더 단단히 포장하므로 성능이 우승합니다.

매우 많은 양의 데이터를 숫자로 묶는 경우 읽어야합니다. 모든 프로그래머가 기억에 대해 알아야 할 것 Ulrich Drepper에 의해. 데이터 캐시의 효율을 극대화하는 것에 대해 6 장에 집중하십시오.

32 비트 CPU CPU 는 일반적으로 운영에서 32 비트 값이 내부적으로,아직하는 것을 의미하지 않는 경우에는 동일한 작업을 수행하에 8/16 비트 값이다.86 예를 들어,여전히 호환됩니까 8086,운영할 수 있는 분수의 등록합니다.는 경우에 등록은 32 비트 와이드,운영할 수 있습니다 만에 첫 번째 16 첫 번째는 8 비트의 등록 없을 것입니다 느린니다.이 개념은 심지어 의해 채택되었 x86_64,어 레지스터는 64 비트,그러나 그들은 여전히 작동할 수 있습만에 첫 번째 32,16,또는 8 비트입니다.

또한 86Cpu 를 항상을 로드하는 전체 캐시 라인에서 메모리하지 않는 경우,이미에서는 캐쉬,그리고 캐쉬 라인보다 더 크 4 어쨌든 바이트(32 비트 Cpu 오 8 또는 16 바이트)및 따라서 선적에는 2 바이트 메모리에서 똑같이 빠르게 로딩 4 바이트 메모리에서.면 처리 많은 값을 메모리에서 16 비트 값을 수 있습니다 실제로는 것보다 훨씬 빠르 32 비트 값이 있기 때문에 더 적은 메모리를 전송합니다.는 경우 캐시선은 8 바이트,네 16 비트 값을 당 캐시 라인,아직 두 32 비트 값에 따라서 사용하는 경우 16 비트 수를 하나의 메모리 액세스를 모든 값을 사용하여,32 비트 수신 모든 두 값의 결과로,두 배의 전송을 처리하기 위한 큰 int 배열입니다.

다른 Cpu,다음과 같 PPC 예를 들어,수 없는 프로세스의 일부만 등록하고,그들이 항상 프로세스 전체 등록합니다.그러나 이러한 Cpu 에는 일반적으로 특별한 로드 작업을 수행할 수 있는 그들을,예를 들어,드 16 비트 값을 메모리에서 확장,그것은 32 비트 쓰 등록합니다.나중에 그들은 특별한 스토어 이루어지는 작업에서 값을 등록하고 단점은 지난 16 비트 메모리에 다시;모두 작업해야만 하나의 CPU 사이클,같은 32 비트 load/store 것이 없다 그래서 속도의 차이다.그리고 이후 PPC 서만 작업을 수행할 수 있습니다 산수 작업에서 레지스터(과는 달리 86 수 있는 운영하는 메모리에 직접적으로),이 load/store 절차는 어쨌든지 사용 32 비트 수 또는 16 비트 수.

유일한 단점,당신이 체인의 여러 작업에서 32 비트 CPU 할 수 있는 운영뿐만 아니라 전체 레지스터는 32 비트의 결과는 마지막 작업을 할 수 있습을 잘라"뒤로"16 비트를하기 전에 다음 작업을 수행,그렇지 않으면 결과가 정확하지 않을 수 있습니다.이러한 줄은 단 하나의 CPU 사이클만(하는 간단하고 작동),그리고 컴파일러는 매우 알아내는 좋은 때와 같은 줄은 정말 필요하고를 떠날 때 그것을 밖으로 있지 않을 것이 어떤 영향을 최종 결과에 따라,그래서 그러한 절단되지 않을 수행한 후에 모든 지침,그것은 단지 수행된 경우에는 정말 피할 수 있습니다.일부 Cpu 에 제공하는 다양한"강화된 지침"을 만들은 다시 불필요하고 내가 많이 봤는 코드에서 내 삶이 예상한 뒤,아직 보고서 생성된 어셈블리 코드를 컴파일러에서 발견하는 방법을 완전히 방지.

그래서를 기대할 경우에는 일반 규칙에 여기에,나는 당신을 실망해야합니다.도할 수 있는지에 대해 말 16 비트 작업은 똑같이 빠른 속도를 32 비트로 작업으며 말할 수 있는지에 대해 32bit 작업은 항상 빠르게 할 수 있습니다.따라 달라도 무슨 정확하게 코드고 그 숫자와 그것을 어떻게 하는 것입니다.본 벤치마크가 32 조금 작업이 빠르게 특정 32 비트 Cpu 보다 동일한 코드 16 비트와 작업,그러나 또한 이미 보았을 반대되는 사실이다.심지어 스위칭 중 하나에서 컴파일러는 다른 하나 또는 업그레이드 버전을 컴파일러 수 차례로 이미 주위에 모든 것을 다시합니다.내가 말할 수 있습 다음과 같다:누구든지 주장하는 작업을 반바지는 크게보다 느리게 작업을 수여 주시기 바랍 견본을 제공하는 소스 코드를 요구하는 그 이름은 CPU 와 컴파일러 그는 그 사용을 위한 테스트,이후 경험하지 못한 것에 대해 지난 10 년이다.될 수 있습은 어떤 상황,어디로 작동 수은 어쩌면 1-5%더 빠르고,아직 아래에 아무것도 10%지 않은"상당한"고 질문 가치가있을 낭비하는 두 번의 메모리 어떤 경우에만 있기 때문에 그것을 살 수 있습니다 당신이 2%의 성능은?나는 그렇게 생각하지 않습니다.

때에 따라 다르지. CPU 바운드 인 경우 32 비트 CPU에서 32 비트 작업이 16 비트보다 빠릅니다. 메모리 바운드 인 경우 (특히 L2 캐시 미스가 너무 많으면) 짜낼 수있는 가장 작은 데이터를 사용하십시오.

CPU와 L2 Misses를 모두 측정 할 프로파일 러를 사용하는 것을 찾을 수 있습니다. 인텔의 vtune. 동일한 부하로 앱을 2 번 실행하고 2 개의 실행이 앱의 핫스팟의 한보기로 병합되며 각 코드 라인에 대해 해당 라인에 얼마나 많은 사이클이 소비되었는지 확인할 수 있습니다. 고가의 코드 라인에서 0 캐시 미스가 표시되면 CPU 바운드입니다. 많은 미스가 보이면 기억에 묶여 있습니다.

조언을 듣지 마십시오.

이것은 아마도 사용중인 하드웨어/컴파일러에 크게 의존 할 것입니다. 빠른 테스트는이 질문에 대한 짧은 작업을해야합니다. 여기에 질문을 작성하는 것보다 테스트를 작성하는 데 시간이 줄어 듭니다.

대규모 데이터 세트에서 작동하는 경우 가장 큰 관심사는 메모리 발자국입니다. 이 경우 좋은 모델은 CPU가 무한히 빠르다고 가정하고 메모리에서 얼마나 많은 데이터를 이동 해야하는지 걱정하는 데 시간을 보내는 것입니다. 실제로, CPU는 이제 너무 빠르기 때문에 때로는 데이터를 인코딩 (예 : 압축)하는 것이 더 효율적입니다. 이렇게하면 CPU는 더 많은 작업 (디코딩/코딩)을 수행하지만 메모리 대역폭은 실질적으로 줄어 듭니다.

따라서 데이터 세트가 크면 16 비트 정수를 사용하는 것이 좋습니다. 목록이 정렬되면 차동 또는 실행 길이 인코딩이 포함 된 코딩 체계를 설계하여 메모리 대역폭을 훨씬 줄일 수 있습니다.

32 비트를 말하면 x86을 의미한다고 가정 할 것입니다. 16 비트 산술은 상당히 느립니다. 피연산자 크기의 접두사가 디코딩을 만듭니다. 진짜 느린. 따라서 임시 변수를 짧은 int 또는 int16_t로 만들지 마십시오.

그러나 X86은 16 및 8 비트 정수를 32 또는 64 비트 레지스터에 효율적으로로드 할 수 있습니다. (movzx / movsx : Zero and Sign Extension). 따라서 배열 및 구조 필드에 짧은 int를 자유롭게 사용하십시오. 그러나 임시 변수에 int를 사용하거나 오래 사용하십시오.

그러나 두 개의 짧은 정수를 함께 추가하는 경우 CPU 패키지는 단일 패스의 두 값을 병렬로 추가 할 것인가 (따라서 버스의 4 바이트 대역폭에 걸쳐)?

그것은 말도 안됩니다. 로드/저장 지침은 L1 캐시와 상호 작용하며 제한 요인은 OP의 수입니다. 너비는 관련이 없습니다. 예를 들어 Core2 : 1 부하 및 너비에 관계없이 사이클 당 1 개의 저장. L1 캐시에는 L2 캐시에 대한 128 또는 256 비트 경로가 있습니다.

로드가 병목 현상 인 경우로드 후 교대 또는 마스크로 분할되는 하나의 넓은 하중이 도움이 될 수 있습니다. 또는 SIMD를 사용하여 병렬로로드 후 포장을 풀지 않고 데이터를 병렬로 처리하십시오.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top