일반적으로 for 루프보다 더 빠른 방법은 없습니다. 그러나 몇 가지 사항을 고려하여 컴파일러에서 루프를 최적화하는 것이 더 쉽습니다.
- 사용 가능한 가장 큰 정수 유형을 한 번에 메모리에로드하십시오. 그러나 버퍼의 정수 유형 크기만큼 균등하게 나누지 않는 길이의 버퍼가 있으면주의해야합니다.
- 가능한 경우 하나의 루프 반복에서 여러 값을 처리하십시오. 이렇게하면 벡터화가 컴파일러에서 훨씬 간단 해집니다. 다시 말하지만 버퍼 길이에주의해야합니다.
- 코드의 짧은 부분에서 루프를 여러 번 실행하려면 위쪽이 아닌 0으로 계산되는 루프 인덱스를 사용하고 배열 길이에서 빼십시오. 이렇게하면 CPU의 분기 예측자가 쉽게 계산할 수 있습니다 무슨 일이 일어나고 있는지.
- 컴파일러에서 제공하는 명시 적 벡터 확장을 사용할 수 있지만 코드 이동성이 떨어집니다.
- 궁극적으로 어셈블리에 루프를 작성하고 CPU에서 제공하는 벡터 명령을 사용할 수는 있지만 완전히 불가능합니다.
- [편집] 또한 OpenMP 또는 유사한 API를 사용하여 루프를 여러 스레드로 나눌 수 있지만 대용량 메모리에서 작업을 수행하는 경우에만 개선 될 수 있습니다.
C99 긴 바이트가 128 비트라고 가정하고, 버퍼의 시작은 포인트 3을 고려하지 않고 16 바이트로 정렬됩니다. 두 메모리 버퍼의 비트 연산은 매우 유사합니다 .
size_t len = ...;
char *buffer = ...;
size_t const loadd_per_i = 4
size_t iters = len/sizeof(long long)/loads_per_i;
long long *ptr = (long long *) buffer;
long long xorvalue = 0x5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5eLL;
// run in multiple threads if there are more than 4 MB to xor
#pragma omp parallel for if(iters > 65536)
for (size_t i = 0; i < iters; ++i) {
size_t j = loads_per_i*i;
ptr[j ] ^= xorvalue;
ptr[j+1] ^= xorvalue;
ptr[j+2] ^= xorvalue;
ptr[j+3] ^= xorvalue;
}
// finish long longs which don't align to 4
for (size_t i = iters * loads_per_i; i < len/sizeof(long long); ++i) {
ptr[i] ^= xorvalue;
}
// finish bytes which don't align to long
for (size_t i = (len/sizeof(long long)) * sizeof(long long); i < len; ++i) {
buffer[i] ^= xorvalue;
}
컴파일러는 해당 루프를 최적화합니다 (예 : 벡터화). 또한 [OpenMP] (http://openmp.org/) 또는 [OpenCL] (http://www.khronos.org/opencl)도 고려하십시오. 아마도 CPU 대역폭이 아니라 메모리 대역폭이 병목입니다. –
어떤 운영 체제, 어떤 프로세서, 어떤 컴파일러, 최적화 플래그가 있습니까? –
어떤 비트 연산입니까? –