• <em id="6vhwh"><rt id="6vhwh"></rt></em>

    <style id="6vhwh"></style>

    <style id="6vhwh"></style>
    1. <style id="6vhwh"></style>
        <sub id="6vhwh"><p id="6vhwh"></p></sub>
        <p id="6vhwh"></p>
          1. 国产亚洲欧洲av综合一区二区三区 ,色爱综合另类图片av,亚洲av免费成人在线,久久热在线视频精品视频,成在人线av无码免费,国产精品一区二区久久毛片,亚洲精品成人片在线观看精品字幕 ,久久亚洲精品成人av秋霞

            matlab乘方(matlab乘方用什么符號?)

            更新時間:2023-03-02 12:24:15 閱讀: 評論:0

            出處 | AI前線

            短短幾年,由 MIT CSAIL 實驗室開發的編程語言 Julia 已然成為編程界的新寵,尤其在科學計算領域炙手可熱。很大部分是因為這門語言結合了 C 語言的速度、Ruby 的靈活、Python 的通用性,以及其他各種語言的優勢于一身。那么你知道為什么 Julia 的速度能做到那么快嗎?這并不是因為更好的編譯器,而是一種更新的設計理念,Julia 在開發之初就將這種理念納入其中,而這也是關注“人生苦短”的 Python 所欠缺的。為什么要選擇 Julia?因為它比其他腳本語言更快,它在具備 Python、MATLAB、R 語言開發速度的同時,又能生成與 C 語言和 Fortran 一樣快的代碼。

            但 Julia 新手對這種說法可能會有點懷疑。

            為什么其他腳本語言不也提升一下速度?Julia 可以做到的,為什么其他腳本語言做不到?你能提供基準測試來證明它的速度嗎?這似乎有違“天底下沒有免費的午餐”的道理。它真的有那么完美嗎?

            很多人認為 Julia 運行速度很快,因為它是即時編譯(JIT)型的(也就是說,每條語句都使用編譯的函數來運行,這些函數要么在使用之前進行即時編譯,要么在之前已經編譯過并放在緩存中)。這就引出了一個問題:Julia 是否提供了比 Python 或 R 語言(MATLAB 默認使用 JIT)更好的 JIT 實現?因為人們在這些 JIT 編譯器上所做的工作比 Julia 要多得多,所以我們憑什么認為 Julia 這么快就會超過這些編譯器?但其實這完全是對 Julia 的誤解。

            我想以一種非常直觀的方式說明,Julia 的速度之所以快,是因為它的設計決策。Julia 的的核心設計決策是通過多重分派實現專門化的類型穩定性,編譯器因此可以很容易地生成高效的代碼,同時還能夠保持代碼的簡潔,讓它“看起來就像一門腳本語言”。

            但是,在本文的示例中,我們將看到 Julia 并不總是像其他腳本語言那樣,我們必須接受“午餐不全是免費”的事實。

            要看出它們之間的區別,我們只需要看看基本的數學運算。

            Julia 中的數學運算

            一般來說,Julia 中的數學運算與其他腳本語言中的數學運算看起來是一樣的。它們的數字都是“真正的數字”,比如 Float64 就是 64 位浮點數或者類似于 C 語言中的“double”。Vector{Float64}與 C 語言 double 數組的內存布局是一樣的,都可以很容易地與 C 語言進行互操作(實際上,在某種意義上,“Julia 是構建在 C 語言之上的一個層”),從而帶來更高的性能。

            使用 Julia 進行一些數學運算:

            復制代碼

            a = 2+2b = a/3c = a÷3 #div tab completion, means integer divisiond = 4*5println([a;b;c;d]) [4.0, 1.33333, 1.0, 20.0]

            我在這里使用了 Julia 的 unicode 制表符補全功能。Julia 允許使用 unicode 字符,這些字符可以通過制表符實現 Latex 風格的語句。同樣,如果一個數字后面跟著一個變量,那么不需要使用 * 運算符就可以進行乘法運算。例如,下面的 Julia 的代碼是合法的:

            復制代碼

            α = 0.5?f(u) = α*u; ?f(2)sin(2π) -2.4492935982947064e-16類型穩定性和代碼內省

            類型穩定性是指一個方法只能輸出一種可能的類型。例如:*(::Float64,::Float64) 輸出的類型是 Float64。不管你給它提供什么參數,它都會返回一個 Float64。這里使用了多重分派:“*”操作符根據它看到的類型調用不同的方法。例如,當它看到浮點數時,就會返回浮點數。Julia 提供了代碼自省宏,可以看到代碼被編譯成什么東西。因此,Julia 不只是一門普通的腳本語言,還是一門可以讓你處理匯編的腳本語言!和其他很多語言一樣,Julia 被編譯成 LLVM (LLVM 是一種可移植的匯編格式)。

            復制代碼

            @code_llvm 2*5 ; Function *; Location: int.jl:54define i64 @"julia_*_33751"(i64, i64) {top: %2 = mul i64 %1, %0 ret i64 %2}

            這段代碼的意思是:執行一個浮點數乘法操作,然后返回結果。我們也可以看一下匯編代碼。

            復制代碼

            @code_native 2*5 .text; Function * {; Location: int.jl:54 imulq %rsi, %rdi movq %rdi, %rax retq nopl (%rax,%rax);}

            “*”函數被編譯成與 C 語言或 Fortran 中完全相同的操作,這意味著它可以達到相同的性能(盡管它是在 Julia 中定義的)。因此,Julia 不僅可以“接近”C 語言,而且實際上可以得到相同的 C 語言代碼。那么在什么情況下會發生這種情況?

            Julia 的有趣之處在于,上面的這個問題其實問得不對,正確的問題應該是:在什么情況下代碼不能被編譯成像 C 語言或 Fortran 那樣?這里的關鍵是類型穩定性。如果一個函數是類型穩定的,那么編譯器就會知道函數在任意時刻的類型,就可以巧妙地將其優化為與 C 語言或 Fortran 相同的匯編代碼。如果它不是類型穩定的,Julia 必須進行昂貴的“裝箱”,以確保在操作之前知道函數的類型是什么。

            這是 Julia 與其他腳本語言之間最關鍵的不同點。

            好的方面是 Julia 的函數(類型穩定)基本上就是 C 語言或 Fortran 的函數,因此“^”(乘方)運算速度很快。那么,類型穩定的 ^(::Int64,::Int64) 會輸出什么?

            復制代碼

            2^5 32

            復制代碼

            2^-5 0.03125

            這里我們會得到一個錯誤。為了確保編譯器可以為“^”返回一個 Int64,它必須拋出一個錯誤。但在 MATLAB、Python 或 R 語言中這么做是不會拋出錯誤的,因為這些語言沒有所謂的類型穩定性。

            如果沒有類型安全性會怎樣?讓我們看一下代碼:

            復制代碼

            @code_native ^(2,5) .text; Function ^ {; Location: intfuncs.jl:220 pushq %rax movabsq $power_by_squaring, %rax callq *%rax popq %rcx retq nop;}

            現在,我們來定義自己的整數乘方運算。與其他腳本語言一樣,我們讓它變得更“安全”:

            復制代碼

            function expo(x,y) if y>0 return x^y el x = convert(Float64,x) return x^y endend expo (generic function with 1 method)

            現在運行一下看看行不行:

            復制代碼

            println(expo(2,5))expo(2,-5) 320.03125

            再來看看匯編代碼。

            復制代碼

            @code_native expo(2,5) .text; Function expo {; Location: In[8]:2 pushq %rbx movq %rdi, %rbx; Function >; {; Location: operators.jl:286; Function <; {; Location: int.jl:49 testq %rdx, %rdx;}} jle L36; Location: In[8]:3; Function ^; {; Location: intfuncs.jl:220 movabsq $power_by_squaring, %rax movq %rsi, %rdi movq %rdx, %rsi callq *%rax;} movq %rax, (%rbx) movb $2, %dl xorl %eax, %eax popq %rbx retq; Location: In[8]:5; Function convert; {; Location: number.jl:7; Function Type; {; Location: float.jl:60L36: vcvtsi2sdq %rsi, %xmm0, %xmm0;}}; Location: In[8]:6; Function ^; {; Location: math.jl:780; Function Type; {; Location: float.jl:60 vcvtsi2sdq %rdx, %xmm1, %xmm1 movabsq $__pow, %rax;} callq *%rax;} vmovsd %xmm0, (%rbx) movb $1, %dl xorl %eax, %eax; Location: In[8]:3 popq %rbx retq nopw %cs:(%rax,%rax);}

            這是一個非常直觀的演示,說明了 Julia 通過使用類型推斷獲得了比其他腳本語言更高的性能。

            核心思想:多重分派 + 類型穩定性 => 速度 + 可讀性

            類型穩定性是 Julia 區別于其他腳本語言的一個關鍵特性。事實上,Julia 的核心思想是這樣的:

            多重分派允許一種語言將函數調用分派給類型穩定的函數。

            這就是 Julia 的核心思想,現在讓我們花點時間深入了解一下。如果函數內部具有類型穩定性(也就是說,函數內的任意函數調用也是類型穩定的),那么編譯器就會知道每一步的變量類型,它就可以在編譯函數時進行充分的優化,這樣得到的代碼基本上與 C 語言或 Fortran 相同。多重分派在這里可以起到作用,它意味著“*”可以是一個類型穩定的函數:對于不同的輸入,它有不同的含義。但是,如果編譯器在調用“*”之前能夠知道 a 和 b 的類型,那么它就知道應該使用哪個“*”方法,這樣它就知道 c=a*b 的輸出類型是什么。這樣它就可以將類型信息一路傳下去,從而實現全面的優化。

            我們從中可以學到一些東西。首先,為了實現這種級別的優化,必須具有類型穩定性。大多數語言為了讓用戶可以更輕松地編碼,都沒有在標準庫中提供這種特性。其次,需要通過多重分派來專門化類型函數,讓腳本語言語法“看上去更顯式”一些。最后,需要一個健壯的類型系統。為了構建非類型穩定的乘方運算,我們需要使用轉換函數。因此,要在保持腳本語言的語法和易用性的同時實現這種原始性能必須將語言設計成具有多重分派類型穩定性的語言,并提供一個健壯的類型系統。

            Julia 基準測試

            Julia 官網提供的基準測試只是針對編程語言組件的執行速度,并沒有說是在測試最快的實現,所以這里存在一個很大的誤解。R 語言程序員一邊看著使用 R 語言實現的 Fibonacci 函數,一邊說:“這是一段很糟糕的代碼,不應該在 R 語言中使用遞歸,因為遞歸很慢”。但實際上,Fibonacci 函數是用來測試遞歸的,而不是用來測試語言的執行速度的。

            Julia 使用了類型穩定函數的多重分派機制,因此,即使是早期版本的 Julia 也可以優化得像 C 語言或 Fortran 那樣。非常明顯,幾乎在所有情況下,Julia 都非常接近 C 語言。當然,也有與 C 語言不一樣的地方,我們可以來看看這些細節。首先是在計算 Fibonacci 數列時 C 語言比 Julia 快 2.11 倍,這是因為這是針對遞歸的測試,而 Julia 并沒有完全為遞歸進行過優化。Julia 其實也可以加入這種優化(尾遞歸優化),只是出于某些原因他們才沒有這么做,最主要是因為:可以使用尾遞歸的地方也可以使用循環,而循環是一種更加健壯的優化,所以他們建議使用循環來代替脆弱的尾遞歸。

            Julia 表現不太好的地方還有 rand_mat_stat 和 par_int 測試。這主要是因為邊界檢查導致的。在大多數腳本語言中,如果你試圖訪問超出數組邊界的元素就會出錯,Julia 默認情況下也會這么做。

            復制代碼

            function test1() a = zeros(3) for i=1:4 a[i] = i endendtest1() BoundsError: attempt to access 3-element Array{Float64,1} at index [4] Stacktrace: [1] tindex! at ./array.jl:769 [inlined] [2] test1() at ./In[11]:4 [3] top-level scope at In[11]:7

            不過,你可以使用 @inbounds 宏來禁用這個功能:

            復制代碼

            function test2() a = zeros(3) @inbounds for i=1:4 a[i] = i endendtest2()

            這樣你就獲得了與 C 語言或 Fortran 一樣的不安全行為和執行速度。這是 Julia 的另一個有趣的特性:默認情況下是一個安全的腳本語言特性,在必要的時候禁用這個功能,以便獲得性能提升。

            嚴格類型

            除了類型穩定性,你還需要嚴格類型。在 Python 中,你可以將任何東西放入數組中。而在 Julia 中,你只能將類型 T 放入 Vector{T}中。Julia 提供了各種非嚴格的類型,例如 Any。如果有必要,可以創建 Vector{Any},例如:

            復制代碼

            a = Vector{Any}(undef,3)a[1] = 1.0a[2] = "hi!"a[3] = :Symbolica 3-element Array{Any,1}: 1.0 "hi!" :Symbolic

            Union 是另一個不那么極端的抽象類型,例如:

            復制代碼

            a = Vector{Union{Float64,Int}}(undef,3)a[1] = 1.0a[2] = 3a[3] = 1/4a 3-element Array{Union{Float64, Int64},1}: 1.0 3 0.25

            這個 Union 只接受浮點數和整數。不過,它仍然是一個抽象類型。接受抽象類型作為參數的函數無法知道元素的類型(在這個例子中,元素要么是浮點數,要么是整數),這個時候,多重分派優化在這里起不到作用,所以 Julia 此時的性能就不如其他腳本語言。

            所以我們可以得出一個性能原則:盡可能使用嚴格類型。使用嚴格類型還有其他好處:嚴格類型的 Vector{Float64}實際上與 C 語言或 Fortran 是字節兼容的,所以不經過轉換就可以直接用在 C 語言或 Fortran 程序中。

            不免費的午餐

            很明顯,Julia 為了在保持腳本語言特征的同時實現性能目標,做出了非常明智的設計決策。但是,它也為此付出了一些代價。接下來,我將展示 Julia 的一些奇特的東西及其相應的工具。

            性能是可選的

            之前已經說明了 Julia 提供了多種方法來提升性能(比如 @inbounds),但我們不一定要使用它們。你也可以編寫類型不穩定的函數,雖然與 MATLAB、R 語言、Python 一樣慢,但你絕對可以這么做。在對性能要求沒有那么高的地方,可以將其作為一個可選項。

            檢查類型穩定性

            由于類型穩定性非常重要,Julia 為我們提供了一些工具,用來檢查一個函數是不是類型穩定的,其中最重要的是 @code_warntype 宏。讓我們用它來檢查一個類型穩定的函數:

            復制代碼

            @code_warntype 2^5 Body::Int64│220 1 ─ %1 = invoke Ba.power_by_squaring(_2::Int64, _3::Int64)::Int64│ └── return %1

            請注意,它將函數中所有變量都顯示為嚴格類型。那么 expo 會是怎樣的?

            復制代碼

            @code_warntype expo(2,5) Body::Union{Float64, Int64}│?? >2 1 ─ %1 = (Ba.slt_int)(0, y)::Bool│ └── goto #3 if not %1│ 3 2 ─ %3 = π (x, Int64)│? ^ │ %4 = invoke Ba.power_by_squaring(%3::Int64, _3::Int64)::Int64│ └── return %4│ 5 3 ─ %6 = π (x, Int64)││? Type │ %7 = (Ba.sitofp)(Float64, %6)::Float64│ 6 │ %8 = π (%7, Float64)│? ^ │ %9 = (Ba.sitofp)(Float64, y)::Float64││ │ %10 = $(Expr(:foreigncall, "llvm.pow.f64", Float64, svec(Float64, Float64), :(:llvmcall), 2, :(%8), :(%9), :(%9), :(%8)))::Float64│ └── return %10

            請注意,可能的返回值是%4 和%10,它們是不同的類型,因此返回類型被推斷為 Union{Float64,Int64}。為了準確地追蹤這種不穩定性發生的位置,我們可以使用 Traceur.jl:

            復制代碼

            using Traceur@trace expo(2,5) ┌ Warning: x is assigned as Int64└ @ In[8]:2┌ Warning: x is assigned as Float64└ @ In[8]:5┌ Warning: expo returns Union{Float64, Int64}└ @ In[8]:2 32

            在第 2 行,x 被分配了一個 Int,而在第 5 行又被分配了一個 Float64,因此它被推斷為 Union{Float64, Int64}。第 5 行是我們放置顯式轉換調用的地方,這樣我們就確定了問題所在的位置。

            處理必要的類型不穩定性

            首先,我已經證明了某些在 Julia 會出錯的函數在其他腳本語言中卻可以“讀懂你的想法”。在很多情況下,你會發現你可以從一開始就使用不同的類型,以此來實現類型穩定性(為什么不直接使用 2.0^-5?)。但是,在某些情況下,你找不到合適的類型。這個問題可以通過轉換來解決,但這樣會失去類型穩定性。你必須重新考慮你的設計,并巧妙地使用多重分派。

            假設我們有一個 Vector{Union{Float64,Int}}類型的 a,并且可能遇到必須使用 a 的情況,需要在 a 的每個元素上執行大量操作。在這種情況下,知道給定元素的類型將帶來性能的大幅提升,但由于類型位于 Vector{Union{Float64,Int}}中,因此無法在下面這樣的函數中識別出類型:

            復制代碼

            function foo(array) for i in eachindex(array) val = array[i] # do algorithm X on val endend foo (generic function with 1 method)

            不過,我們可以通過多重分派來解決這個問題。我們可以在元素上使用分派:

            復制代碼

            function inner_foo(val) # Do algorithm X on valend inner_foo (generic function with 1 method)

            然后將 foo 定義為:

            復制代碼

            function foo2(array::Array) for i in eachindex(array) inner_foo(array[i]) endend foo2 (generic function with 1 method)

            因為需要為分派檢查類型,所以 inner_foo 函數是嚴格類型化的。因此,如果 inner_foo 是類型穩定的,那么就可以通過專門化 inner_foo 來提高性能。這就導致了一個通用的設計原則:在處理奇怪或非嚴格的類型時,可以使用一個外部函數來處理邏輯類型,同時使用一個內部函數來處理計算任務,實現最佳的性能,同時仍然具備腳本語言的通用能力。

            REPL 的全局作用域性能很糟糕

            Julia 全局作用域的性能很糟糕。官方的性能指南建議不要使用全局作用域。然而,新手可能會意識不到 REPL 其實就是全局作用域。為什么?首先,Julia 是有嵌套作用域的。例如,如果函數內部有函數,那么內部函數就可以訪問外部函數的所有變量。

            復制代碼

            function test(x) y = x+2 function test2() y+3 end test2()end test (generic function with 1 method)

            在 test2 中,y 是已知的,因為它是在 test 中定義的。如果 y 是類型穩定的,那么所有這些工作就可以帶來性能的提升,因為 test2 可以假設 y 是一個整數。現在讓我們來看一下在全局作用域里會發生什么:

            復制代碼

            a = 3function badidea() a + 2enda = 3.0 3.0

            因為沒有使用分派來專門化 badidea,并且可以隨時更改 a 的類型,因此 badidea 在編譯時無法進行優化,因為在編譯期間 a 的類型是未知的。但是,Julia 允許我們聲明常量:

            復制代碼

            const a_cons = 3function badidea() a_cons + 2end badidea (generic function with 1 method)

            請注意,函數將使用常量的值來進行專門化,因此它們在設置后應該保持不變。

            在進行基準測試時會出現這種情況。新手會像下面這樣對 Julia 進行基準測試:

            復制代碼

            a = 3.0@time for i = 1:4 global a a += iend 0.000006 conds (4 allocations: 64 bytes)

            但是,如果我們將它放在一個函數中,就可以實現優化。

            復制代碼

            function timetest() a = 3.0 @time for i = 1:4 a += i endendtimetest() # First time compilestimetest() 0.000001 conds0.000000 conds

            這個問題非常容易解決:不要在 REPL 的全局作用域內進行基準測試或計算執行時間。始終將代碼放在函數中,或將它們聲明為 const。

            結 論

            速度是 Julia 的設計目標。類型穩定性和多重分派對 Julia 編譯的專門化起到了關鍵的作用。而要達到如此精細的類型處理水平,以便盡可能有效地實現類型穩定性,并在不完全可能的情況下實現性能優化,需要一個健壯的類型系統。

            英文原文:

            https://ucidatascienceinitiative.github.io/IntroToJulia/Html/WhyJulia

            本文發布于:2023-02-28 21:09:00,感謝您對本站的認可!

            本文鏈接:http://www.newhan.cn/zhishi/a/1677731055105076.html

            版權聲明:本站內容均來自互聯網,僅供演示用,請勿用于商業和其他非法用途。如果侵犯了您的權益請與我們聯系,我們將在24小時內刪除。

            本文word下載地址:matlab乘方(matlab乘方用什么符號?).doc

            本文 PDF 下載地址:matlab乘方(matlab乘方用什么符號?).pdf

            標簽:乘方   符號   matlab
            相關文章
            留言與評論(共有 0 條評論)
               
            驗證碼:
            推薦文章
            排行榜
            Copyright ?2019-2022 Comsenz Inc.Powered by ? 實用文體寫作網旗下知識大全大全欄目是一個全百科類寶庫! 優秀范文|法律文書|專利查詢|
            主站蜘蛛池模板: 老熟女熟妇一区二区三区| 夜夜躁狠狠躁日日躁2021| 国产av丝袜旗袍无码网站| 婷婷五月深深久久精品| 国产成人AV国语在线观看| 欧美性一区| 久久夜色精品国产噜噜亚洲sv| 无码一级视频在线| 人妻丰满熟妇av无码区| 国产白袜脚足j棉袜在线观看| 亚洲精品一区二区制服| 久久www视频| 一区二区三区四区激情视频 | 国产精品亚洲国际在线看| av中文字幕在线二区| 99久久久国产精品消防器材| 国产av综合一区二区三区| 无码国模国产在线观看免费| 国产一区国产精品自拍| 99re免费视频| 9久9久热精品视频在线观看| 国产99视频精品免费专区| 九色国产精品一区二区久久| 亚洲av无码国产在丝袜线观看| 久久综合狠狠综合久久| 免费网站看V片在线毛| 国产精品美女久久久久久麻豆| 欧美日韩在线亚洲综合国产人| 亚洲一卡2卡3卡4卡 精品| 爱性久久久久久久久| 亚洲国产精品色一区二区| 伊人久久大香线蕉AV网禁呦| 久久久久99人妻一区二区三区| 曰韩无码二三区中文字幕| 免费人成视频x8x8国产| 欧美一a级做爰片大开眼界| 美乳丰满人妻无码视频| 国产a在视频线精品视频下载 | 高清无码爆乳潮喷在线观看| 人妻无码熟妇乱又伦精品视频| 性欧美vr高清极品|