문제

나를 통해 실행하는 메모리 블록의 이진 데이터 바이트다.

현재 내가 뭔가를 하는 다음과 같다:

for (i = 0; i < data->Count; i++)
{   
    byte = &data->Data[i];
    ((*byte & Masks[0]) == Masks[0]) ? Stats.FreqOf1++; // syntax incorrect but you get the point.
    ((*byte & Masks[1]) == Masks[1]) ? Stats.FreqOf1++;
    ((*byte & Masks[2]) == Masks[2]) ? Stats.FreqOf1++;
    ((*byte & Masks[3]) == Masks[3]) ? Stats.FreqOf1++;
    ((*byte & Masks[4]) == Masks[4]) ? Stats.FreqOf1++;
    ((*byte & Masks[5]) == Masks[5]) ? Stats.FreqOf1++;
    ((*byte & Masks[6]) == Masks[6]) ? Stats.FreqOf1++;
    ((*byte & Masks[7]) == Masks[7]) ? Stats.FreqOf1++;
}

는 마스크:

for (i = 0; i < 8; i++)
{
    Masks[i] = 1 << i;
}

(어떻게 든 관리하지 않았으로 그것을 할 수 있는 빠른 루프에서 또는 인라인 함수,그래서 나는 그것을 썼습니다.)

누군가는 방법에 대한 제안을 개선하는 첫 번째 루프?내가 오히려 경험을 가진을 받고 내려 비트입니다.

이처럼 보일 수도 있 바보 같은 일을 하는 것입니다.하지만 내가를 구현하는 과정에서 압축 알고리즘이 있습니다.내가 원하는 비트에 액세스하는 부분을 아래로 오른쪽.

감사합니다!

PS:이것은 Visual Studio2008 컴파일러입니다.그래서 그것은 좋은 것입하는 경우 제안을 적용하는 컴파일러입니다.

PPS:나는 그냥 깨달아,내가 증가할 필요가 없랍니다.하나는 것 충분하다.그 차이를 계산하는 총 비트입니다.그러나는 것이 특정 단 계산합니다.내가 정말 원하는 빠른 수행은 조금 추출합니다.

편집:조회 테이블 아이디어는 앞으로 좋은 것입니다.나는 깨닫지만 내가 질문을 제기된 제목입니다.기 때문에 무슨 말 하고 싶지 않은 수를 비트이지만,서로 액세스 비트입니다.

다른 편집:그것은 가능한 발전에 의해 포인터를 하나의 비트는 데이터가?

다른 편집:모든 주셔서 감사합니다 당신의 답변이 지금까지.

내가 무엇을 구현하려면 다음 단계에서는 nonsophisticated binary arithmetic coder 하지 않는 분석이 있다.그래서 나에만 관심이 있는 단일 비트니다.결국 그것이 될 것이다 Context-adaptive BAC 그러나 나는 그것을 떠날 것입니다.

가공 4 바이트를 1 대신 바이트 될 수 있습니다.그러나 루프 32 비트 이상의 비용이 많이 드는뿐만 아니라,그렇지 않나요?

도움이 되었습니까?

해결책

지 않았다 정말 이해 당신이 무엇을 행하려고 노력하는 것입니다.하지만 경우에 당신은 단지에 접근하고자 하는 비트 비트맵에,당신은 이러한 사용할 수 있습니다(이 검증되지 않은!!!) 기능:

#include <stddef.h>

_Bool isbitset(unsigned char * bitmap, size_t idx)
{
    return bitmap[idx / 8] & (1 << (idx % 8)) ? 1 : 0;
}

void setbit(unsigned char * bitmap, size_t idx)
{
    bitmap[idx / 8] |= (1 << (idx % 8));
}

void unsetbit(unsigned char * bitmap, size_t idx)
{
    bitmap[idx / 8] &= ~(1 << (idx % 8));
}

void togglebit(unsigned char * bitmap, size_t idx)
{
    bitmap[idx / 8] ^= (1 << (idx % 8));
}

편집: Ok,I 생각 이해 당신이 무엇을 하고 싶:빠르고 반복을 통해 시퀀스의 비트입니다.따라서,우리가 사용하고 싶지 않은 랜덤 액세스 기능이 위에서만 읽고 전체의 말씀 데이터를 한꺼번에.

당신이 하나를 사용할 수 있습니다 unsigned integer 유형은 당신처럼,하지만 당신은 선택해야 하는 가능성에 해당하는 단어의 크기를 포함됩니다.제가 갈게요 uint_fast32_tstdint.h:

uint_fast32_t * data = __data_source__;
for(; __condition__; ++data)
{
    uint_fast32_t mask = 1;
    uint_fast32_t current = *data;
    for(; mask; mask <<= 1)
    {
        if(current & mask)
        {
            // bit is set
        }
        else
        {
            // bit is not set
        }
    }
}

에서 내부 루프 설정할 수 있는 비트와

*data |= mask;

unset 비트와

*data &= ~mask;

와 전환을 가진 비

*data ^= mask;

경고: 코드에 예기치 않게 동작할 수 있습니다 on-endian 아키텍처!

다른 팁

가장 빠른 방법은 아마도 바이트 값의 조회 테이블과 해당 바이트의 비트 수를 구축하는 것입니다. 적어도 Google에서 인터뷰 할 때 답이되었습니다.

수십 가지 비트 관련 제품에 대한 다음 링크를 참조하십시오. 비트 twiddling 핵

각 바이트 값 (256)을 1의 수에 매핑하는 테이블을 사용하십시오. (0의 #은 단지 (8 - # of 1)입니다. 그런 다음 바이트를 반복하고 여러 조회 및 비교 대신 각 바이트에 대해 단일 조회를 수행하십시오. 예를 들어:

int onesCount = 0;
for (i = 0; i < data->Count; i++)
{   
    byte = &data->Data[i];
    onesCount += NumOnes[byte];
}
Stats.FreqOf1 += onesCount;
Stats.FreqOf0 += (data->Count * 8) - onesCount;

미리 계산 된 조회 테이블을 사용할 수 있습니다.

static int bitcount_lookup[256] = { ..... } ; /* or make it a global and compute the values in code */

...

for( ... ) 
   byte = ... 
   Stats.FreqOf1 += bitcount_lookup[byte];

다음은 32 비트 정수의 1 비트를 계산하는 방법입니다 (Java의 기반 Integer.bitCount(i) 방법):

unsigned bitCount(unsigned i) {
    i = i - ((i >> 1) & 0x55555555);
    i = (i & 0x33333333) + ((i >> 2) & 0x33333333);
    i = (i + (i >> 4)) & 0x0f0f0f0f;
    i = i + (i >> 8);
    i = i + (i >> 16);
    return i & 0x3f;
}

따라서 데이터를 INT에 캐스트하고 4 바이트 단계로 앞으로 나아갈 수 있습니다.

여기에 단일 32 비트 값으로 채찍질 한 간단한 것이 있지만, 여러 비트에 적응하기가 어렵지 않을 것입니다 ....

int ones = 0;
int x = 0xdeadbeef;
for(int y = 0;y < 32;y++)
{
    if((x & 0x1) == 0x1) ones++;
    x = (x >> 1);
}

printf("%x contains %d ones and %d zeros.\n", x, ones, 32-ones);

그러나 프로세스의 값을 수정합니다. 보관 해야하는 데이터 에서이 작업을 수행하는 경우 먼저 사본을 만들어야합니다.

__Ams 에서이 작업을 수행하는 것은 아마도 더 나을 것입니다. 아마도 더 빠를 수도 있지만 컴파일러가 얼마나 잘 최적화 할 수 있는지 말하기는 어렵습니다 ...

각 솔루션마다 고려하면 각 솔루션에는 단점이 있습니다. 조회 테이블 또는 비트 시프터 (광산과 같은)에는 모두 단점이 있습니다.

래리

ttobiass - 인라인 기능은 당신이 말하는 것과 같은 응용 프로그램에서 중요하지만, 명심해야 할 것들이 있습니다. 너 할 수 있다 인라인 코드에서 성능을 얻으십시오. 몇 가지를 기억하십시오.

  • 디버그 모드의 인라인은 존재하지 않습니다. (당신이 그것을 강요하지 않는 한)
  • 컴파일러는 적합하다고 생각되는 기능을 인라인으로 작동합니다. 종종 기능을 인라인으로 말하면 전혀 수행하지 않을 수 있습니다. __forceinline을 사용하더라도. 인라인에 대한 자세한 내용은 MSDN을 확인하십시오.
  • 특정 기능 만 감소 할 수도 있습니다. 예를 들어 재귀 기능을 인화 할 수 없습니다.

C/C ++ 언어에 대한 프로젝트 설정에서 최상의 성능을 얻을 수 있으며 코드를 구성하는 방법. 이 시점에서 힙 대 스택 작업, 컨벤션 호출, 메모리 정렬 등을 이해하는 것이 중요합니다.

나는 이것이 당신의 질문에 정확히 답하지는 않지만, 당신은 성능과 최고의 성능을 얻는 방법을 언급하며, 이러한 것들이 핵심입니다.

링크 마차에 가입하려면 :계산 비트

이것이 조기 최적화의 경우가 아니고 마지막 펨토초마다 진정으로 짜야한다면, 각 바이트 값의 비트 카운트로 한 번 채우는 256 요소 정적 배열이 더 나을 것입니다.

stats.freqof1 += bitcounttable [byte

그리고 루프가 완료되면 :

stats.freqof0 = ((data-> count * 8) -STATS.FREQOF1)

책에 이것에 대한 다른 기술에 대한 전체 장이 있습니다. 아름다운 코드. Google 도서에서 읽을 수 있습니다 (대부분) 여기에서 시작합니다.

비트를 추출하는 더 빠른 방법은 사용하는 것입니다.

bitmask= data->Data[i];

while (bitmask)
{
    bit_set_as_power_of_two= bitmask & -bitmask;
    bitmask&= bitmask - 1;
}

비트 세트를 계산하려면 캐시 당 LUT가 빠르지 만 인터리브 비트 계산 방법으로 일정한 시간에도 할 수 있습니다. 이 답변의 링크.

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