2013-10-04 2 views
0

IEEE754 부동 소수점을 사용할 때 32 비트 변수의 상위 9 비트를 0으로 만드는 두 가지 방법을 발견했습니다. 그들 중 어느 것이 다른 것보다 낫습니까?비트 마스킹 대 시프트 (+ java 바이트 코드)

Java 관련 추가 : 명령어 효율성에 대한 정보를 제공하는 목록이 있습니까? 나는 무작위로 BIPUSH가 일반적으로 LDC보다 빠르다고 생각하지만 다른 것은별로 없다고 판명했습니다.

// 10111111110010100011110101110001 bits 
// 00000000010010100011110101110001 significand 

int bits = 0b10111111110010100011110101110001; 
int significand = bits & 0b11111111111111111111111; 
int significand2 = bits <<9>>> 9; 

바이트 코드 ...

L4 
    LINENUMBER 49 L4 
    ILOAD 0 
    LDC 8388607 // = 0b11111111111111111111111 
    IAND 
    ISTORE 5 
L5 
    LINENUMBER 50 L5 
    ILOAD 0 
    BIPUSH 9 
    ISHL 
    BIPUSH 9 
    IUSHR 
    ISTORE 6 

감사합니다. :)

+1

간단한 정수 연산이 최신 프로세서에서 중요한 성능 문제가되는 경우는 매우 드뭅니다. 조건부 분기 및 캐시 누락이 훨씬 더 중요 할 수 있습니다. –

답변

3

바이트 코드는 이식성있는 중간 언어입니다. 적절한 성능을 얻으려면 최신 JVM이 적시에 네이티브 코드로 컴파일하므로 너무 많이 읽지 않도록하십시오. CPU가 실제로 실행하게 될 것은 매우 다르게 보일 수 있습니다. 생성 된 네이티브 코드를 분석하여 X가 Y보다 성능이 우수한 이유에 대한 결론을 이끌어 낼 수 있습니다.

생성 된 어셈블러 코드를 인쇄하는 방법은 JVM에 따라 다릅니다. 핫스팟에 대한 지침은 여기를 참조하십시오. (예 : Oracle JDK 및 OpenJDK) http://mechanical-sympathy.blogspot.com/2013/06/printing-generated-assembly-code-from.html

0

일반적으로 시프트 조작이 빨라야합니다. 다음은 간단한 자바 테스트 및 결과 값입니다 :

int bits = 0b10111111110010100011110101110001; 

long time = System.nanoTime(); 
int significand; 
for (int i = 0; i < 1000000000; i++) { 
    significand = bits & 0b11111111111111111111111; 
} 
System.out.println(String.format("Time: %f (ms)", 
    (System.nanoTime() - time)/1000000f)); 

long time2 = System.nanoTime(); 
for (int i = 0; i < 1000000000; i++) { 
    significand = bits <<9>>> 9; 
} 
System.out.println(String.format("Time 2: %f (ms)", 
    (System.nanoTime() - time2)/1000000f)); 

시간 1 : 7.003190 (MS)
시간 2 : 2.633435 (MS)

이는 물론, 반복 엄청난 수의 결과.

+0

필자는 내 코드 (JProfiler)를 프로파일 링했고 shinfting 메소드는 실제로 더 빠르다 (1.56x). 그러나 좀 더 일반적인 응답 또는 적어도 힌트는 어디에서 찾았는지 조니의 답에서 찾았습니다. 어쨌든 대단히 고마워. :) –