2015-01-02 46 views
1

考慮下面的代碼段的第一VS第二呼叫的(朱)性能的函數

bar(x) = for i = 1:9999 x+x*x-x+x end # Define the "bar" function 
print("First try: "); @time bar(0.5) 
print("Second try: "); @time bar(0.5) 
bar(x) = for i = 1:9999 x+x*x-x+x end # Redefine the same "bar" function 
print("Third try: "); @time bar(0.5) 
print("Fourth try: "); @time bar(0.6) 

輸出是

First try: elapsed time: 0.002738996 seconds (88152 bytes allocated) 
Second try: elapsed time: 3.827e-6 seconds (80 bytes allocated) 
Third try: elapsed time: 0.002907554 seconds (88152 bytes allocated) 
Fourth try: elapsed time: 2.395e-6 seconds (80 bytes allocated) 

爲什麼是第二(和第四)嘗試這樣比第一個(和第三個)嘗試更快(並佔用更少的內存)?

+1

據我瞭解,Julia是一個即時編譯器。因此,第一個(和第三個)運行是編譯代碼(爲此需要分配),第二個(和第四個)運行只是運行先前編譯的代碼。 –

+0

焦點話題:如果您重新運行代碼而不進行修改會發生什麼? Python創建.pyc文件(一種編譯的源代碼)。如果pyc文件仍然與源文件匹配,則不需要重新編譯它(呃,不是所有的東西)。 =>更快 –

+0

哦,好的。這完全有道理。我會認爲編譯會在函數的定義中發生,而不是在第一次運行時發生。我猜你可以從你的評論中作出回答。謝謝@保羅 –

回答

3

朱莉婭,據我所知,是一個即時編譯器。所以第一個(和第三個)運行是編譯代碼(爲此需要分配),第二個(和第四個)運行只是運行先前編譯的代碼

3

只是爲了擴展Paul的答案:加速來自Julia的類型推斷和多次調度。假設您第一次使用float評估函數:JIT(即時編譯器)計算出參數的類型並寫入適當的LLVM代碼。如果您隨後使用整數評估相同的函數,則會編譯不同的LLVM代碼。在您調用該函數的下列時間,它將根據參數的類型分派不同的LLVM代碼。這就是爲什麼在定義函數時編譯通常不合理的原因。

你可以閱讀更多關於這個here例如(有多個調度噸引用的文件中!)

考慮,例如:

bar(x) = for i = 1:9999 x+x*x-x+x end 

print("First try with floats: "); @time bar(0.5) 
print("Second try with floats: "); @time bar(0.5) 

print("First try with integers: "); @time bar(1) 
print("Second try with integers: "); @time bar(1) 

這給:

First try with floats: elapsed time: 0.005570773 seconds (102440 bytes allocated) 
Second try with floats: elapsed time: 5.762e-6 seconds (80 bytes allocated)  
First try with integers: elapsed time: 0.003584026 seconds (86896 bytes allocated)  
Second try with integers: elapsed time: 6.402e-6 seconds (80 bytes allocated)