Neden bu kadar inanılmaz derecede hızlı bu C program var mı? | Netgez.com
SORU
18 Temmuz 2014, Cuma


Neden bu kadar inanılmaz derecede hızlı bu C program var mı?

Küçük bir kıyaslama, Ruby, JavaScript ve Python için C derleyicileri/farklı tercümanların performansını karşılaştırmak için yazdım . Beklendiği gibi, (optimize) C dillerine atıyor ama hangi bunu yapar faktörü inanılmaz derecede yüksek olduğu ortaya çıktı.

Sonuçlar:

sven@jet:~/tmp/js$ time node bla.js              # * JavaScript with node *
0

real    0m1.222s
user    0m1.190s
sys 0m0.015s
sven@jet:~/tmp/js$ time ruby foo.rb              # * Ruby *
0

real    0m52.428s
user    0m52.395s
sys 0m0.028s
sven@jet:~/tmp/js$ time python blub.py           # * Python with CPython *
0

real    1m16.480s
user    1m16.371s
sys 0m0.080s

sven@jet:~/tmp/js$ time pypy blub.py             # * Python with PyPy *
0

real    0m4.707s
user    0m4.579s
sys 0m0.028s

sven@jet:~/tmp/js$ time ./cpp_non_optimized 1000 1000000 # * C   with -O0 (gcc) *
0

real    0m1.702s
user    0m1.699s
sys 0m0.002s
sven@jet:~/tmp/js$ time ./cpp_optimized 1000 1000000     # * C   with -O3 (gcc) *
0

real    0m0.003s # (!!!) <---------------------------------- WHY?
user    0m0.002s
sys 0m0.002s

Eğer kimseye optimize C kodu büyüklükte üç siparişleri üzerinde diğer her şeyden daha hızlı olduğunu neden bir açıklama sağlayabilir merak ediyorum.

C kriter derleme zamanında ön işlem sonucu önlemek için komut satırı parametreleri kullanır.

Aşağıda, gönderilmesinin eşdeğer olması gereken farklı dil testleri, kaynak kodları yerleştirdim. Ayrıca, optimize edilmiş C derleyici çıkış (gcc kullanarak) için derleme kod verilmiştir. Optimize Meclisi bakarken, derleyici için tek bir kriter iki döngüler birleştirilmiş gibi görünüyor, ama yine de bir döngü var!

JavaScript:

var s = 0;
var outer = 1000;
var inner = 1000000;

for (var i = 0; i < outer;   i) {
    for (var j = 0; j < inner;   j) {
          s;
    }
    s -= inner;
}
console.log(s);

Python:

s = 0
outer = 1000
inner = 1000000

for _ in xrange(outer):
    for _ in xrange(inner):
        s  = 1
    s -= inner
print s

Ruby:

s = 0
outer = 1000
inner = 1000000

outer_end = outer - 1
inner_end = inner - 1

for i in 0..outer_end
  for j in 0..inner_end
    s = s   1
  end
  s = s - inner
end
puts s

C :

#include <iostream>
#include <cstdlib>
#include <cstdint>

int main(int argc, char* argv[]) {
  uint32_t s = 0;
  uint32_t outer = atoi(argv[1]);
  uint32_t inner = atoi(argv[2]);
  for (uint32_t i = 0; i < outer;   i) {
    for (uint32_t j = 0; j < inner;   j)
        s;
    s -= inner;
  }
  std::cout << s << std::endl;
  return 0;
}

Meclis-S -O3 -std=c 0 x gcc ile C kodu derlemek ():

    .file   "bar.cpp"
    .section    .text.startup,"ax",@progbits
    .p2align 4,,15
    .globl  main
    .type   main, @function
main:
.LFB1266:
    .cfi_startproc
    pushq   %r12
    .cfi_def_cfa_offset 16
    .cfi_offset 12, -16
    movl    $10, íx
    movq    %rsi, %r12
    pushq   %rbp
    .cfi_def_cfa_offset 24
    .cfi_offset 6, -24
    pushq   %rbx
    .cfi_def_cfa_offset 32
    .cfi_offset 3, -32
    movq    8(%rsi), %rdi
    xorl    %esi, %esi
    call    strtol
    movq    16(%r12), %rdi
    movq    %rax, %rbp
    xorl    %esi, %esi
    movl    $10, íx
    call    strtol
    testl   ëp, ëp
    je  .L6
    movl    ëp, ëx
    xorl    êx, êx
    xorl    íx, íx
    .p2align 4,,10
    .p2align 3
.L3:                             # <--- Here is the loop
    addl    $1, êx             # <---
    cmpl    êx, ëx           # <---
    ja  .L3                      # <---
.L2:
    movl    íx, %esi
    movl    $_ZSt4cout, íi
    call    _ZNSo9_M_insertImEERSoT_
    movq    %rax, %rdi
    call    _ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_
    popq    %rbx
    .cfi_remember_state
    .cfi_def_cfa_offset 24
    popq    %rbp
    .cfi_def_cfa_offset 16
    xorl    êx, êx
    popq    %r12
    .cfi_def_cfa_offset 8
    ret
.L6:
    .cfi_restore_state
    xorl    íx, íx
    jmp .L2
    .cfi_endproc
.LFE1266:
    .size   main, .-main
    .p2align 4,,15
    .type   _GLOBAL__sub_I_main, @function
_GLOBAL__sub_I_main:
.LFB1420:
    .cfi_startproc
    subq    $8, %rsp
    .cfi_def_cfa_offset 16
    movl    $_ZStL8__ioinit, íi
    call    _ZNSt8ios_base4InitC1Ev
    movl    $__dso_handle, íx
    movl    $_ZStL8__ioinit, %esi
    movl    $_ZNSt8ios_base4InitD1Ev, íi
    addq    $8, %rsp
    .cfi_def_cfa_offset 8
    jmp __cxa_atexit
    .cfi_endproc
.LFE1420:
    .size   _GLOBAL__sub_I_main, .-_GLOBAL__sub_I_main
    .section    .init_array,"aw"
    .align 8
    .quad   _GLOBAL__sub_I_main
    .local  _ZStL8__ioinit
    .comm   _ZStL8__ioinit,1,1
    .hidden __dso_handle
    .ident  "GCC: (Ubuntu 4.8.2-19ubuntu1) 4.8.2"
    .section    .note.GNU-stack,"",@progbits

CEVAP
18 Temmuz 2014, Cuma


İyileştirici sonraki satırı ile birlikte iç döngü hayır-op bir ve ortadan da işe yaradı. Ne yazık ki dış döngü de ortadan kaldırmak için yönetilen değil.

Node.js örneğin daha hızlı unoptimized C örnek daha V8 (düğümün JİT derleyicisi) döngüler en az birini ortadan kaldırmak için yönetilen belirten olduğunu unutmayın. Ancak, optimizasyon (herhangi bir JİT derleyici gibi) iyileştirme için fırsatları denge olmalı ve profil-güdümlü optimizasyonu re bunu yapmanın maliyeti karşı bazı ek yükü vardır.

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

YORUMLAR

SPONSOR VÄ°DEO

Rastgele Yazarlar

  • bobinire

    bobinire

    24 EYLÃœL 2006
  • Elly

    Elly

    3 EKÄ°M 2005
  • NextGenWindows

    NextGenWindo

    8 Kasım 2011