커다란 배열에 대해 광범위한 스와핑 연산을 수행하는 C 프로그램이 있습니다. 그것은 단단한 루프에서 모듈러스 연산을합니다. 실제로 [-N -N [N
의 제곱의 힘을 가진 정수가 있고 [0, N [. -4 => 0, -3 => 1, -2 => (2) -1 => 3, 0 => 0, ..., 3 => 3모듈로 최적화
예
처음에는 아래의 버전 1을 시도했지만 조건부 표현이 있어도 버전 2가 실제로 더 빠르다는 사실에 놀랐습니다.
이 특수한 경우 버전 2가 버전 1보다 빠른 이유를 설명 할 수 있습니까?
버전 1 :
#define N (1<<(3*5))
inline int modBitAnd(int x)
{
return (x & (N-1));
}
런타임 (전체 프로그램) 17.1 초
버전 2
inline int modNeg1(int x)
{
return (x < 0 ? x + N : x);
}
런타임 : 전체 14.6 초 (프로그램)
프로그램은 GCC 4.8.2에서 컴파일됩니다. -std = c99 -O3.
편집 :
int en(uint16_t* p, uint16_t i, uint16_t v)
{
uint16_t n1 = p[modNeg1((int)i - 1)];
uint16_t n2 = p[modBitAnd((int)i + 1)];
uint16_t n3 = p[modNeg1((int)i - C_WIDTH)];
uint16_t n4 = p[modBitAnd((int)i + C_WIDTH)];
return d(n1,v) + d(n2,v) + d(n3,v) + d(n4,v);
}
void arrange(uint16_t* p)
{
for(size_t i=0; i<10000000; i++) {
uint16_t ia = random(); // random integer [0|2^15[
uint16_t va = p[ia];
uint16_t ib = random(); // random integer [0|2^15[
uint16_t vb = p[ib];
if(en(p,ia,vb) + en(p,ib,va) < en(p,ia,va) + en(p,ib,vb)) {
p[ia] = vb;
p[ib] = va;
}
}
}
int d(uint16_t a, uint16_t b)
예컨대 거리 함수이다 : 여기
내 프로그램의 메인 루프 abs((int)a-(int)b)
.
이것은 p
초기화 방법은 다음과 같습니다
uint16_t* p = malloc(sizeof(uint16_t)*N);
for(unsigned i=0; i<N; i++) *p++ = i;
먼저 나는 사방 modBitAnd
을 사용하지만, modNeg1
이 acutally 빠르게 사용할 수 있습니다 두 경우에 대한 것을 알아 냈다.
컴파일러에서 생성 된 어셈블리 코드를 살펴 보았습니까? – Medinoc
두 번째 버전은 모듈로가 발생하지 않기 때문에 나머지 결과를 전달하지 않으면 제대로 작동하지 않습니다 –
어떤 플랫폼 (32 또는 64 비트)입니까? 또한 [전체 코드 예제 게시] (http://meta.stackoverflow.com/a/258849/509868) 또는 디스 어셈블리 목록을 참조하십시오. – anatolyg