幾個月前,我開始使用茱莉亞,在幾周聽到人們讚揚它的各種特徵後決定試一試。我學到的東西越多,我越喜歡它的風格,融合了以高級語言表達概念的便捷性,並注重速度和可用性。我實現了一個我也用Julia的C++和R編寫的模型,發現Julia版本的運行速度比R版本快得多,但仍比C++稍慢。即使如此,Julia的代碼也比其他兩種語言更清晰。這是值得的,特別是當我推廣這個模型時,爲擴大Julia代碼範圍所做的工作量要遠遠低於其他語言中可能的工作量。我用Julia吧?
最近,我一直專注於讓我的Julia代碼跑得更快,因爲我需要運行這個模型數萬億次。在這樣做時,我一直以@code_warntype
,@time
,@profile
和ProfileView
和track-allocation
標誌爲指導。大。這個工具箱並不像其他語言的剖析工具那麼好,但它仍然指出了很多瓶頸。
我發現我在我的代碼中正好具有我喜歡的Julia的高級表達能力,當我重寫表達式以避免不必要的分配時,我失去了這種表達能力。作爲一個簡單的例子,我最近改變的代碼行,超過清單讀
sum([x*y for x in some_list, y in similar_list])
到一個循環,進行迭代,並且增加了一個狀態變量。不是火箭科學,我明白爲什麼不分配數組要快一點。其實這是一個很多雖然更快。所以我做了類似的事情,避免使用Dicts或者「感覺」適合這個問題的複合類型,但是我可以手動跟蹤臨時平行數組中的索引,這是我憎惡的編碼風格,但顯然運行當我重複創建和短暫使用小型數據結構的許多次的特定操作時,速度更快。
總的來說,這在很大程度上是好的,因爲我已經將編寫簡短方法的指令放在心上,所以構成我自己較短方法行爲的更高級方法不需要「擔心」更短的方法工作;較短的可以笨重地閱讀,而不會讓我的程序的核心難以閱讀。
但這讓我想知道我是否「失去了一些東西」。如果語言的全部內容(對於我來說是一個非理論相關的最終用戶)部分是爲了將速度與易於開發/思考/閱讀/維護等相結合,即成爲可寫和可用的技術計算語言,那麼這並不意味着我不應該花費時間考慮最快的方式來合併一堆數字,不應該重寫「容易閱讀」或優雅的代碼,利用映射,過濾器和高級函數的概念轉化爲「笨重的」代碼,這些代碼重新發明輪子來表達這些事情,就低層次跟蹤數組索引而言? (我的某些部分期望一個語言的設計背後有如此多的智能,足夠聰明地「弄清楚」,當我寫sum([x * y])時,實際上並不需要分配一個新數組,我只是懶得找出合適的詞來告訴語言,除了通過手動「告訴」整個循環業務之外,我甚至想過編寫@macros
將一些快速表示的代碼「轉換」爲長但更快的loopy表達式,但我認爲如果我基本上試圖擴展編譯器的功能來解決相當直接的問題,這就是我寫這個問題的原因,我必須考慮這個問題。)
也許答案是:「如果你想要真正的高性能代碼,無論如何你都要付出代價。「或者換句話說,快速代碼與令人討厭的不愉快的閱讀循環,數組,跟蹤索引等是快速可讀性權衡空間的有效前沿。如果是這樣,這是完全有效的,因此我不會說我我只是想知道這種編程風格是否真的處於邊界,或者我的經驗是什麼,因爲我的語言不能很好地編程(通過類比,請參閱問題What is your most productive shortcut with Vim?,其中接受的和優秀的答案基本上是OP沒有「得到」它)。我懷疑,即使我已經成功地讓語言做了我想要的東西,那我只是不「獲得」某些東西,但我沒有很好的理解,因爲我擔心我沒有得到的東西對我來說是一個未知的未知數
TL; DR:I爲了獲得更快的性能,我花費了大量時間將我的高級函數調用「分解」爲它們的基本實現(以循環和數組方式),或者表明我沒有想到關於正確編程/使用該語言?
好的我已經閱讀了幾次這個討論,我認爲你的總結非常明智。簡短的答案似乎是「你寫出高層次的東西,用同樣的語言寫下低層次的東西是Julia的巨大好處之一。」這讓我覺得很好。 – Philip
順便說一句,是的,Devectorize.jl正在做我正在考慮爲我的特定情況編寫宏時的想法。它的性能基準使我認爲,對於許多目的而言,僅僅將例程優化爲特定情況值得努力,但我會密切關注其發展。 – Philip