2014-01-24 1 views
3

for 루프를 사용하는 것보다 큰 메모리 블록에서 비트 연산을 수행하는 것이 더 빠르고 (더 빠르고 효율적인) 방법이 있습니까? 옵션을 찾은 후에 std에 멤버 std::bitset이 있다는 것을 알게되었고 값을 변경하지 않고 큰 영역의 메모리를 비트 집합으로 변환 한 다음 조작을 수행하는 것이 더 좋을지 (또는 가능할 지) 궁금합니다. 유형을 다시 정상으로 전환 하시겠습니까?/업데이트메모리 블록에서 비트 연산하는 방법 (C++)

편집 : 나는 메모리 블록이 newint의 배열 또는 뭔가를 할당하고 큰 bitset으로 조작되도록, union 여기에 적용 할 수있는 생각합니다. 작업은 여기에 나온 내용을 토대로 전체 세트에서 수행 할 수있는 것 같습니다 : http://www.cplusplus.com/reference/bitset/bitset/operators/.

+1

컴파일러는 해당 루프를 최적화합니다 (예 : 벡터화). 또한 [OpenMP] (http://openmp.org/) 또는 [OpenCL] (http://www.khronos.org/opencl)도 고려하십시오. 아마도 CPU 대역폭이 아니라 메모리 대역폭이 병목입니다. –

+0

어떤 운영 체제, 어떤 프로세서, 어떤 컴파일러, 최적화 플래그가 있습니까? –

+0

어떤 비트 연산입니까? –

답변

6

일반적으로 for 루프보다 더 빠른 방법은 없습니다. 그러나 몇 가지 사항을 고려하여 컴파일러에서 루프를 최적화하는 것이 더 쉽습니다.

  1. 사용 가능한 가장 큰 정수 유형을 한 번에 메모리에로드하십시오. 그러나 버퍼의 정수 유형 크기만큼 균등하게 나누지 않는 길이의 버퍼가 있으면주의해야합니다.
  2. 가능한 경우 하나의 루프 반복에서 여러 값을 처리하십시오. 이렇게하면 벡터화가 컴파일러에서 훨씬 간단 해집니다. 다시 말하지만 버퍼 길이에주의해야합니다.
  3. 코드의 짧은 부분에서 루프를 여러 번 실행하려면 위쪽이 아닌 0으로 계산되는 루프 인덱스를 사용하고 배열 길이에서 빼십시오. 이렇게하면 CPU의 분기 예측자가 쉽게 계산할 수 있습니다 무슨 일이 일어나고 있는지.
  4. 컴파일러에서 제공하는 명시 적 벡터 확장을 사용할 수 있지만 코드 이동성이 떨어집니다.
  5. 궁극적으로 어셈블리에 루프를 작성하고 CPU에서 제공하는 벡터 명령을 사용할 수는 있지만 완전히 불가능합니다.
  6. [편집] 또한 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; 
} 
+0

openmp에 대한'#pragma omp parallel for'은 특별히 무엇입니까? openmp가 연결되어 있지 않으면 무시됩니다. 맞습니까? 죄송합니다. 지금까지의 멀티 프로세서 경험에는 CUDA 만 포함되었습니다. 또한, 일반적으로 코멘트에서 감사하다고 말하지 않는 것이 좋지만, 답변에 대한 명확한 설명을 요구하고 있기 때문에 나는 괜찮을 것이라고 생각합니다. 그래서 .. 감사합니다!예제 코드를 사용하면 대답/조언을 훨씬 쉽게 이해할 수 있습니다. – ConfusedStack

+0

OpenMP로 컴파일하지 않으면 (일반적으로 GCC에 대해 -fopenmp와 같은 플래그를 전달 함) pragma는 무시되지만 알 수없는 pragma에 대한 경고를 얻을 수 있습니다 . GCC에서는 -Wno-unknown-pragmas를 사용하여 GCC를 끌 수 있습니다. OpenMP는 거의 모든 경우에 pragma를 무시하고 작동하는 단일 스레드 프로그램을 얻을 수있는 방식으로 설계되었습니다. –

관련 문제