Neden 64 int daha uzun yavaştır? | Netgez.com
SORU
7 Kasım 2013, PERŞEMBE


Neden 64 int daha uzun yavaştır?

Windows 8.1 64 Yüzey Pro 2 tablet Java 7 update 45 x 64 (32 bit Java yüklü) ile koşuyorum.

Aşağıdaki kod ben bu tür bir uzun ve bir int i zaman 109ms olduğunda 1688ms alır. Neden 64 bit JVM ile 64 bitlik bir platformda int büyüklük daha uzun (64 bit türü) bir sipariş daha yavaştır?

Sadece benim teorim CPU 32 bit birden 64 bit bir tamsayı eklemek için daha uzun sürer, ama bu pek mümkün görünmüyor. Haswell ripple-carry toplayıcı kullanmıyor sanırım.

Eclipse Kepler bu koÅŸuyorum SR-1, btw.

public class Main {

    private static long i = Integer.MAX_VALUE;

    public static void main(String[] args) {    
        System.out.println("Starting the loop");
        long startTime = System.currentTimeMillis();
        while(!decrementAndCheck()){
        }
        long endTime = System.currentTimeMillis();
        System.out.println("Finished the loop in "   (endTime - startTime)   "ms");
    }

    private static boolean decrementAndCheck() {
        return --i < 0;
    }

}

Burada eşdeğer C kodu (aşağıda), aynı sistem VS 2013 tarafından derlenmiş. sonuçlar Düzenle:uzun: 72265ms int: 74656msBu sonuçlar debug 32 bit modu.

64 bit sürüm:uzun: 875msuzun uzun: 906ms int: 1047ms

Bu gözlemledim sonucu CPU sınırlamaları yerine JVM optimizasyon tuhaflık olduğunu göstermektedir.

#include "stdafx.h"
#include "iostream"
#include "windows.h"
#include "limits.h"

long long i = INT_MAX;

using namespace std;


boolean decrementAndCheck() {
return --i < 0;
}


int _tmain(int argc, _TCHAR* argv[])
{


cout << "Starting the loop" << endl;

unsigned long startTime = GetTickCount64();
while (!decrementAndCheck()){
}
unsigned long endTime = GetTickCount64();

cout << "Finished the loop in " << (endTime - startTime) << "ms" << endl;



}

Bunun tekrar Java 8 RTM çalıştı, önemli bir değişiklik. Edit:

CEVAP
7 Kasım 2013, PERŞEMBE


Benim JVM longs kullandığınızda iç döngü için oldukça basit bu şey yapıyor

0x00007fdd859dbb80: test   êx,0x5f7847a(%rip)  /* fun JVM hack */
0x00007fdd859dbb86: dec    %r11                  /* i-- */
0x00007fdd859dbb89: mov    %r11,0x258(%r10)      /* store i to memory */
0x00007fdd859dbb90: test   %r11,%r11             /* unnecessary test */
0x00007fdd859dbb93: jge    0x00007fdd859dbb80    /* go back to the loop top */

ints kullandığınızda, zor Hileleri,; ilk anladığımı iddia etmiyorum ama içe kıvrık bir döngü Kur gibi görünen bazı screwiness var:

0x00007f3dc290b5a1: mov    %r11d,%r9d
0x00007f3dc290b5a4: dec    %r9d
0x00007f3dc290b5a7: mov    %r9d,0x258(%r10)
0x00007f3dc290b5ae: test   %r9d,%r9d
0x00007f3dc290b5b1: jl     0x00007f3dc290b662
0x00007f3dc290b5b7: add    $0xfffffffffffffffe,%r11d
0x00007f3dc290b5bb: mov    %r9d,ìx
0x00007f3dc290b5be: dec    ìx              
0x00007f3dc290b5c0: mov    ìx,0x258(%r10)   
0x00007f3dc290b5c7: cmp    %r11d,ìx
0x00007f3dc290b5ca: jle    0x00007f3dc290b5d1
0x00007f3dc290b5cc: mov    ìx,%r9d
0x00007f3dc290b5cf: jmp    0x00007f3dc290b5bb
0x00007f3dc290b5d1: and    $0xfffffffffffffffe,%r9d
0x00007f3dc290b5d5: mov    %r9d,%r8d
0x00007f3dc290b5d8: neg    %r8d
0x00007f3dc290b5db: sar    $0x1f,%r8d
0x00007f3dc290b5df: shr    $0x1f,%r8d
0x00007f3dc290b5e3: sub    %r9d,%r8d
0x00007f3dc290b5e6: sar    %r8d
0x00007f3dc290b5e9: neg    %r8d
0x00007f3dc290b5ec: and    $0xfffffffffffffffe,%r8d
0x00007f3dc290b5f0: shl    %r8d
0x00007f3dc290b5f3: mov    %r8d,%r11d
0x00007f3dc290b5f6: neg    %r11d
0x00007f3dc290b5f9: sar    $0x1f,%r11d
0x00007f3dc290b5fd: shr    $0x1e,%r11d
0x00007f3dc290b601: sub    %r8d,%r11d
0x00007f3dc290b604: sar    $0x2,%r11d
0x00007f3dc290b608: neg    %r11d
0x00007f3dc290b60b: and    $0xfffffffffffffffe,%r11d
0x00007f3dc290b60f: shl    $0x2,%r11d
0x00007f3dc290b613: mov    %r11d,%r9d
0x00007f3dc290b616: neg    %r9d
0x00007f3dc290b619: sar    $0x1f,%r9d
0x00007f3dc290b61d: shr    $0x1d,%r9d
0x00007f3dc290b621: sub    %r11d,%r9d
0x00007f3dc290b624: sar    $0x3,%r9d
0x00007f3dc290b628: neg    %r9d
0x00007f3dc290b62b: and    $0xfffffffffffffffe,%r9d
0x00007f3dc290b62f: shl    $0x3,%r9d
0x00007f3dc290b633: mov    ìx,%r11d
0x00007f3dc290b636: sub    %r9d,%r11d
0x00007f3dc290b639: cmp    %r11d,ìx
0x00007f3dc290b63c: jle    0x00007f3dc290b64f
0x00007f3dc290b63e: xchg   %ax,%ax /* OK, fine; I know what a nop looks like */

içe kıvrık döngü kendini sonra:

0x00007f3dc290b640: add    $0xfffffffffffffff0,ìx
0x00007f3dc290b643: mov    ìx,0x258(%r10)
0x00007f3dc290b64a: cmp    %r11d,ìx
0x00007f3dc290b64d: jg     0x00007f3dc290b640

içe kıvrık döngü, kendisi bir sınav ve düz bir döngü için enkaz daha sonra kod:

0x00007f3dc290b64f: cmp    $0xffffffffffffffff,ìx
0x00007f3dc290b652: jle    0x00007f3dc290b662
0x00007f3dc290b654: dec    ìx
0x00007f3dc290b656: mov    ìx,0x258(%r10)
0x00007f3dc290b65d: cmp    $0xffffffffffffffff,ìx
0x00007f3dc290b660: jg     0x00007f3dc290b654

Bu JİT int döngü 16 kez içe kıvrık çünkü 16 kat daha hızlı bir şekilde değer vermez sürüyor, ama long döngü göz önüne sermek değildi yani.

Bütünlüğü için, burada kodu denedim:

public class foo136 {
  private static int i = Integer.MAX_VALUE;
  public static void main(String[] args) {
    System.out.println("Starting the loop");
    for (int foo = 0; foo < 100; foo  )
      doit();
  }

  static void doit() {
    i = Integer.MAX_VALUE;
    long startTime = System.currentTimeMillis();
    while(!decrementAndCheck()){
    }
    long endTime = System.currentTimeMillis();
    System.out.println("Finished the loop in "   (endTime - startTime)   "ms");
  }

  private static boolean decrementAndCheck() {
    return --i < 0;
  }
}

Montaj döker seçenekleri -XX: UnlockDiagnosticVMOptions -XX: PrintAssembly kullanılarak üretildi. Etrafında senin için bu iş de JVM yükleme ile uğraşmak gerekir; tam olarak doğru yerde rastgele bir paylaşımlı kütüphane koymak gerekir ya da başarısız olur unutmayın.

Bunu PaylaÅŸ:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VÄ°DEO

Rastgele Yazarlar

  • Elliot Davin

    Elliot Davin

    28 Kasım 2008
  • Jonathan Morrison

    Jonathan Mor

    24 Mart 2010
  • SunsetTrance

    SunsetTrance

    20 EYLÃœL 2008