최근에 이상한 문제가 발생했을 때 개인 프로젝트를 진행하고있었습니다.
매우 엄격한 루프에서는 0과 15 사이의 값을 가진 정수가 있습니다. 0, 1, 8 및 9의 경우 -1을 얻고 값 4, 5, 12 및 13의 경우 1을 가져와야합니다.
나는 godbolt를 사용하여 몇 가지 옵션을 확인했으며 컴파일러가 if 체인과 같은 방식으로 switch 문을 최적화 할 수없는 것처럼 보였습니다.
링크는 다음과 같습니다 : https://godbolt.org/z/WYVBFl
코드는 다음과 같습니다
const int lookup[16] = {-1, -1, 0, 0, 1, 1, 0, 0, -1, -1, 0, 0, 1, 1, 0, 0};
int a(int num) {
return lookup[num & 0xF];
}
int b(int num) {
num &= 0xF;
if (num == 0 || num == 1 || num == 8 || num == 9)
return -1;
if (num == 4 || num == 5 || num == 12 || num == 13)
return 1;
return 0;
}
int c(int num) {
num &= 0xF;
switch (num) {
case 0: case 1: case 8: case 9:
return -1;
case 4: case 5: case 12: case 13:
return 1;
default:
return 0;
}
}
b와 c가 동일한 결과를 얻을 것이라고 생각했을 때 솔루션 (스위치 양식-다른 형식)이 상당히 느리기 때문에 효율적인 구현을 위해 비트 해킹을 읽을 수 있기를 바랐습니다.
이상하게도, b
비트 해킹으로 컴파일되는 동안 c
거의 최적화되지 않았거나 a
대상 하드웨어 에 따라 다른 경우로 축소되었습니다 .
왜 이러한 불일치가 있는지 설명 할 수 있습니까? 이 쿼리를 최적화하는 '올바른'방법은 무엇입니까?
편집하다:
설명
내가 원하는 스위치 솔루션은 빠른, 또는 유사하게 "깨끗한"해결책이 될 수 있습니다. 그러나 내 컴퓨터에서 최적화로 컴파일하면 if 솔루션이 훨씬 빠릅니다.
시연을위한 빠른 프로그램을 작성했으며 TIO는 로컬에서 찾은 것과 동일한 결과를 얻 습니다.
static inline
룩업 테이블을 사용 하면 속도가 약간 빨라집니다. 온라인으로 사용해보십시오!
if
여전히 박동 switch
(이상한 조회도 빨라집니다) TIO 따를]
-O3
컴파일c
했으며a
또는 보다 나쁘거나b
(c
두 개의 조건부 점프와 약간의 비트 조작, 단 하나의 조건부 점프와 간단한 비트 조작b
)했습니다. 항목 별 테스트보다 순진한 항목보다 낫습니다. 나는 당신이 정말로 무엇을 요구하는지 잘 모르겠습니다. 단순한 사실은 최적화 컴파일러가 설정할 수 있다는 것입니다 어떤 으로 이들을 어떤 이 경우이 선택하는 그래서 다른 사람의, 그것은 또는하지 않을 것입니다 무엇에 대한 하드 및 빠른 규칙이 없다.