문제

내가 읽고 어딘가에 한 번하는 계수 연산자입니다 비효율적이에 작은 임베디드 장치 8 비트 마이크로 컨트롤러가 없는 정수 부서 명령입니다.아마 누군가가 이것을 확인할 수 있습 그러나 내가 생각의 차이는 5~10 시간 느린 보다 정수 부서 작업입니다.

수있는 또 다른 방법이 있나요 이렇게하려면 다른 유지 보다는 변수 및 수동으로 범람하 0 에서 모 포인트는?

const int FIZZ = 6;
for(int x = 0; x < MAXCOUNT; x++)
{
    if(!(x % FIZZ)) print("Fizz\n"); // slow on some systems
}

대:

방법 현재는 그것을 하:

const int FIZZ = 6;
int fizzcount = 1;
for(int x = 1; x < MAXCOUNT; x++)
{
    if(fizzcount >= FIZZ) 
    {
        print("Fizz\n");
        fizzcount = 0;
    }
}
도움이 되었습니까?

해결책

Ah,기쁨의 비트 or 연산입니다.의 부작용은 많은 부문에 루틴은 계수-그래서 몇 가지 경우에서야 부문에 실제로보다 더 빨리 계수입니다.내가 관심을 참조 원본을 가지고 이 정보에서.프로세서 승수는 흥미로운 분열 루틴이 사용하는 배수지만,당신이 얻을 수 있습에서 부과하는 계수와 함께 다른 두 가지 단계(곱하기 및 빼기)그래서 그것은 여전히 비교할 수 있습니다.는 경우 프로세서가 내장 부서에서 일상적인 당신이 그것을 참조는 또한 제공합니다 나머지입니다.

여전히,거기에 작은 지점의 번호가 이론이념 모듈산 요구하는 공부하는 경우 당신이 정말로 이해하려면을 최적화하는 방법을 계수 작업입니다.모듈 arithmatic,예를 들어,매우 편리성 마법 사각형.

그래서,정맥에서는,여기 매우 낮은 자세한 내용을 확인하십시오. 에서 수학의 계수는 예 x 해야하는,당신을 보여 간단한 방법을 비교할 수 있습 division:


아마 더 나은 방법에 대해 생각하는 문제입의 측면에서 번호 지 모듈로를 참조하시기 바랍니다.예를 들어,귀하의 계산하는 것이 목적이 다우 모 7where DOW16 비트 표현의의 날 주일입니다.당신을 사용하면 다음과 같이 쓸 수 있다:

 DOW = DOW_HI*256 + DOW_LO

 DOW%7 = (DOW_HI*256 + DOW_LO) % 7
       = ((DOW_HI*256)%7  + (DOW_LO % 7)) %7
       = ((DOW_HI%7 * 256%7)  + (DOW_LO%7)) %7
       = ((DOW_HI%7 * 4)  + (DOW_LO%7)) %7

현 방식으로,당신이 할 수 있는 별도로 계산한 모듈 7 결과에 대한 높고 낮은 바이트입니다.곱하기위한 결과를 높여 4 에 추가 낮은 그리고 마지막으로 계산 결과 모듈 7.

컴퓨팅 mod7 의 결과는 8 비트 번호에서 수행할 수 있습니다 비슷한 패션이다.를 작성할 수 있는 8 비트 숫자에 진처럼 그렇:

  X = a*64 + b*8 + c

는 a,b 및 c 는 3 비트 숫자입니다.

  X%7 = ((a%7)*(64%7) + (b%7)*(8%7) + c%7) % 7
      = (a%7 + b%7 + c%7) % 7
      = (a + b + c) % 7

64%7 = 8%7 = 1

물론,a,b,c

  c = X & 7
  b = (X>>3) & 7
  a = (X>>6) & 7  // (actually, a is only 2-bits).

가능한 한 가장 큰 값 a+b+c7+7+3 = 17.그래서,당신은 필요 하나 더 진수 단계입니다.전체(이 검증되지 않은)C 버전이 될 수 있는 은 다음과 같이 쓰:

unsigned char Mod7Byte(unsigned char X)
{
    X = (X&7) + ((X>>3)&7) + (X>>6);
    X = (X&7) + (X>>3);

    return X==7 ? 0 : X;
}

을 보냈다 약간의 시간을 쓰고 그림 버전입니다.실제 구현 는 약간 다른 것보다 위에서 설명

Mod7Byte:
       movwf        temp1        ;
       andlw        7        ;W=c
       movwf        temp2        ;temp2=c
       rlncf   temp1,F        ;
       swapf        temp1,W ;W= a*8+b
       andlw   0x1F
       addwf        temp2,W ;W= a*8+b+c
       movwf        temp2   ;temp2 is now a 6-bit number
       andlw   0x38    ;get the high 3 bits == a'
       xorwf        temp2,F ;temp2 now has the 3 low bits == b'
       rlncf   WREG,F  ;shift the high bits right 4
       swapf   WREG,F  ;
       addwf        temp2,W ;W = a' + b'

 ; at this point, W is between 0 and 10


       addlw        -7
       bc      Mod7Byte_L2
Mod7Byte_L1:
       addlw        7
Mod7Byte_L2:
       return

여기에 liitle 일상적인 알고리즘을 테스트하기 위해

       clrf    x
       clrf    count

TestLoop:
       movf        x,W
       RCALL   Mod7Byte
       cpfseq count
        bra    fail

       incf        count,W
       xorlw   7
       skpz
        xorlw        7
       movwf   count

       incfsz        x,F
       bra        TestLoop
passed:

마지막으로,16-비트가 결과(는 내가 테스트하지 않았습니다),당신 쓰:

uint16 Mod7Word(uint16 X)
{
 return Mod7Byte(Mod7Byte(X & 0xff) + Mod7Byte(X>>8)*4);
}

스콧


다른 팁

당신이 계산하는 수 mod 어떤 두 개의 전원을 사용할 수 있습 bit-wise and 연산자입니다.그냥 하나를 빼기에서 두번째 숫자입니다.예를 들어:

x % 8 == x & 7
x % 256 == x & 255

몇 가지 주의 사항:

  1. 에만 작동 는 경우 두번째 숫자는 전원의 두 가지.
  2. 그것은 단지 해당하는 경우 모듈은 항상 긍정적이다.C 및 C++표준 지정하지 않은 기호의 계수를 때 첫 번째 숫자는 부정적인(전까지는 C++11 그것을 보장하는 것은 부정적인 것은 무엇 대부분의 컴파일러는 이미 하고).비트의 로그인 비트,그래서 그것은 항상 긍정적인(즉그것은 진실성 계수지,나머지).그것처럼 들리는 당신이 무엇을 원하는 어쨌든 그러나.
  3. 귀하의 컴파일러는 아마 이미 이 때 할 수 있습니다,그래서 대부분의 경우 그 가치가있을 수 있습니다.

이 있는 오버헤드는 대부분의 시간에서 모듈을 사용하여하지 않는 능력 2.이 관계없이 프로세서(AFAIK)어 프로세서로 계수 연산자는 몇 주기를 느리게 나눈에 반대하는 마스크 작업입니다.

대부분의 경우에는 이것은 최적화하는 고려 가치가있다,그리고 확실히 가치가 계산이 자신의 바로 가기를 작업(특히 경우 그것은 여전히 포함 분할 또는 곱).

그러나,하나 엄지손가락의 규칙을 배열을 선택한 크기 등등입니다.하의 힘 2.

그래서 만약을 계산하는 요일을 수있다,뿐만 아니라 사용하%7 관 를 설치하는 경우 원형 버퍼의 약 100 항목을...왜 그것을 만들 128.할 수 있습니다 다음 쓰%128 장(모든)컴파일러를 만들 것입이&0x7F

지 않는 한 당신이 정말로 필요한 높은 성능에 여러 개의 임베디드 플랫폼에,변경하지 않는 방법 당신은 코드에 대한 성능을 가지 이유 때까지 당신은 프로필!

코드 서면 불편을 최적화를 위한 성능은 하드 디버깅하고 유지 하기 어렵다.테스트를 작성한 경우,그리고 그것은 프로필에 당신의 대상입니다.일단 당신이 알고 실제 비용의 계수를 결정하는 경우 다른 솔루션은 가치분입니다.

@마태복음은 옳습니다.이것을 보십시오:

int main() {
  int i;
  for(i = 0; i<=1024; i++) {
    if (!(i & 0xFF)) printf("& i = %d\n", i);
    if (!(i % 0x100)) printf("mod i = %d\n", i);
  }
}
x%y == (x-(x/y)*y)

이게 도움이 되었으면 좋겠습니다.

에 포함된 세계"계수는"작업을 할 필요가 있는 종종하는 사람을 분명으로 조금 작업을 함께 할 수 있는'&'과'|'고 때로는'>>'.

당신은에 액세스하는 어떤 프로그래밍 하드웨어에 포함된 장치입니까?같은 카운터와 같은?그렇다면,당신은 수도에 쓸 수 있는 하드웨어 기반의 모 단위,사용하는 대신 시뮬레이션%.(나가는 한 번에 VHDL.가 확실하지 않다면 내가 여전히 코드 하지만입니다.)

당신이 마음,당신이 말했다는 사단은 5~10 배 빠릅니다.당신은 일을 고려 사업부,곱하기 및 빼기를 시뮬레이션 모드는?(편집:오해 원본다.나는 생각하는 것이 이상 사단보다 더 빨리 모드,그들은 같은 작업입니다.)

에서 특정한 경우,하지만,당신은 확인 모드 6.6=2*3.그래서 당신은 수면 몇 가지 작은 이득이한 경우 먼저 선택하는 경우 적어도 중요한 비트이었 0.다음과 같습니다.

if((!(x & 1)) && (x % 3))
{
    print("Fizz\n");
}

만약 당신이 그렇게 한다면,하지만,나는 추천인지 확인하는 어떤 이익을 얻을,예을 위한 프로파일러.고 일부는 댓글입니다.나는 나쁜 생각이 다음 사람에서 볼드지 않습니다.

당신이 정말로 확인된 장치는 당신이 필요합니다.는 모든 어셈블리 언어 보았(x86,68000)를 구현하는 계수를 사용 부문이다.

실제로,어셈블리 작업 부문의 결과를 반환 부문하고 나머지 두 개의 서로 다른 등록합니다.

하지 않는 것이 이것은 반드시 더 좋은,하지만 당신은 수 내부 루프는 항상을 피하고,외부 루프 반복되는 이 모든 일정 횟수입니다.당신은 아마도 가지고하는 특별한 경우 최종 몇 가지 단계는 경우 MAXCOUNT 지 균등하게 나눌에 의해 소다.

는 말했다,나는 것이 좋을 연구하고 성능 프로파일링에서도 플랫폼의 정확한 아이디어를 얻을 수 있는 성능의 제약이 있습니다.될 수 있습이 훨씬 더 많은 생산성의 부하를 최적화 노력입니다.

@제프 V:나는 그것으로 문제가!(저쪽에는 너의 원래 코드를 찾고 있었 모 6 이제 당신은 기본적으로 찾고 있는 모 8).당신은 일을 계속 추가+1!희망이 귀하의 컴파일러 최적화하는 거리,하지만 왜 그냥 테스트에서 시작 2 가 MAXCOUNT 클?마지막으로,당신은 반환하는 진정한 매 시간(x+1)로 나눌 수 없 8.은 당신이 무엇을 원하는가?(나는 가정은 하지만 그냥을 확인합니다.)

를 위한 모듈 6 변경할 수 있습니다 Python 코드는 C/C++:

def mod6(number):
    while number > 7:
        number = (number >> 3 << 1) + (number & 0x7)
    if number > 5:
        number -= 6
    return number

Print 문의 주문을 것입니다 크기 이상도 가장 느린의 구현 계수 연산자입니다.그래서 기본적으로 코멘트"천천히는 일부 시스템에서"해야한다"슬로우 모든 시스템에서".

또한,두 개의 코드를 제공 하지 않는 동일한 것입니다.에서 두 번째 라인

if(fizzcount >= FIZZ)

는 항상 거짓 그래서"소 "이지 인쇄했습니다.

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