Imp*_*p54 4 performance types julia
我正在向某些函数添加类型,即为了速度和清晰度。我对此有几个问题。我在这里问他们所有人,因为我看过其他帖子这样做。问题以粗体显示,以便于识别。
\n我想向一个函数添加类型,用于计算向量中负值的数量。我想让它与 Int 和 Float 兼容,就像非类型化函数一样。虽然方便,但 Chris Rackauckas 建议不要这样做,请参阅如何声明可以具有 int 和 float 的数组类型的第一条评论,
\n\n\n您想同时使用整数和浮点数吗?由于性能原因,不建议这样做。但如果您愿意,可以使用 Union{Int64,Float64} 作为类型。
\n
如果由于某种原因需要多态函数,那么更好的方法似乎是通过Union
. 然而,对于这种特殊情况,由于Number
和是和Real
的超类型,我认为它们会比非类型化版本稍快一些。Int64
Float64
然而,至少在我的简单测试中,情况似乎并非如此。我测试了一个没有参数类型的函数,另一个带有Any
,以及两个带有类型Number
和 的函数Real
,两者都是Float64
和的超类型Int64
。
notypes\nmedian time: 1.006 ms (0.00% GC)\nmean time: 1.152 ms (12.60% GC)\n\nany\nmedian time: 1.054 ms (0.00% GC)\nmean time: 1.197 ms (12.05% GC)\n\nunion\nmedian time: 1.062 ms (0.00% GC)\nmean time: 1.210 ms (12.09% GC)\n\nnumber\nmedian time: 1.110 ms (0.00% GC)\nmean time: 1.315 ms (14.18% GC)\n\nreal\nmedian time: 1.015 ms (0.00% GC)\nmean time: 1.168 ms (12.70% GC)\n\nfloat\nmedian time: 728.131 \xce\xbcs (0.00% GC)\nmean time: 829.031 \xce\xbcs (11.53% GC)\n
Run Code Online (Sandbox Code Playgroud)\nAny
显然,无类型函数与类型为和 的函数之间没有显着的改进Number
。该Real
功能似乎有非常轻微的改进,并且该Float64
功能是唯一具有明显改进的功能。
一个函数是否只有类型Int
并且Float
通常比没有类型的函数更快? Union{Int64,Float64}
是只有两种类型的超类型,Number
与 和不同Real
,跨越更多类型。这就是为什么我认为该Union
函数会比其他函数(Float
版本除外)更快。一般来说 s 和非类型化一样慢吗?Union
与保持非类型化相比,使用Number
和 等超类型键入函数是否有任何性能改进?Float
为每种可能的参数类型定义一个函数是最佳的朱利安实践吗?在这种情况下,Int64
并且Float64
.
为了方便而不是为了性能,是否有更短的方法来定义 Int-Float 函数?也许,通过在一开始就定义一个新类型?我尝试这样做:
\nabstract type IF64 <: Union{Int64,Float64} end\n
Run Code Online (Sandbox Code Playgroud)\n但出现错误
\ninvalid subtyping in definition of IF64\n
Run Code Online (Sandbox Code Playgroud)\n另外,函数定义中的含义是什么?N
(例如where {T<:Union{Int64,Float64},N}
下面countMPvec_arrUnion
给出的 \ 的定义)。
最后,为什么该Float
函数比其他函数占用更少的内存?( 609.06 KiB
v. 921.56 KiB
)(这是基准测试的输出;代码如下)
all other functions\n memory estimate: 921.56 KiB\n allocs estimate: 38979\nfloat\n memory estimate: 609.06 KiB\n allocs estimate: 28979\n
Run Code Online (Sandbox Code Playgroud)\n测试的完整代码:
\n#= -------------------\n The different versions of the function\n -------------------\n=#\nfunction countMPvec_notypes(vec)\n nneg = 0\n lvec = length(vec)\n for i in 1:lvec\n if (vec[i] < 0)\n nneg += 1\n end\n end\n npos = lvec - nneg\n return (nneg,npos)\nend\n\nfunction countMPvec_any(vec :: Any)\n nneg = 0\n lvec = length(vec)\n for i in 1:lvec\n if (vec[i] < 0)\n nneg += 1\n end\n end\n npos = lvec - nneg\n return (nneg,npos)\nend\n\n# Works with Int and Float !!!\nfunction countMPvec_arrUnion(vec :: Array{T,1}) where {T<:Union{Int64,Float64},N}\n nneg = 0\n lvec = length(vec)\n for i in 1:lvec\n if (vec[i] < 0)\n nneg += 1\n end\n end\n npos = lvec - nneg\n return (nneg,npos)\nend\n\n# Works with Int and Float !!!\nfunction countMPvec_arrNumber(vec :: Array{T,1}) where {T<:Number,N}\n nneg = 0\n lvec = length(vec)\n for i in 1:lvec\n if (vec[i] < 0)\n nneg += 1\n end\n end\n npos = lvec - nneg\n return (nneg,npos)\nend\n\n# Works with Int and Float !!!\nfunction countMPvec_arrReal(vec :: Array{T,1}) where {T<:Real,N}\n nneg = 0\n lvec = length(vec)\n for i in 1:lvec\n if (vec[i] < 0)\n nneg += 1\n end\n end\n npos = lvec - nneg\n return (nneg,npos)\nend\n\nfunction countMPvec_arrFloat(vec :: Array{Float64,1})\n nneg = 0\n lvec = length(vec)\n for i in 1:lvec\n if (vec[i] < 0)\n nneg += 1\n end\n end\n npos = lvec - nneg\n return (nneg,npos)\nend\n\n#= -------------------\n Functions for benchmark\n -------------------\n=#\nnums = [1.3; -2; 5]\nnitertest = 10000\n\nfunction test_notypes()\n for i in 1:nitertest\n countMPvec_notypes(nums)\n end\nend\nfunction test_any()\n for i in 1:nitertest\n countMPvec_any(nums)\n end\nend\nfunction test_arrUnion()\n for i in 1:nitertest\n countMPvec_arrUnion(nums)\n end\nend\nfunction test_arrNumber()\n for i in 1:nitertest\n countMPvec_arrNumber(nums)\n end\nend\nfunction test_arrReal()\n for i in 1:nitertest\n countMPvec_arrReal(nums)\n end\nend\nfunction test_arrFloat()\n for i in 1:nitertest\n countMPvec_arrFloat(nums)\n end\nend\n
Run Code Online (Sandbox Code Playgroud)\n然后是基准单元。其中每一项都应该单独运行。此外,最后给出了每个单元格的完整输出:
\nimport BenchmarkTools\nprintln("notypes")\n@BenchmarkTools.benchmark test_notypes()\n\nprintln("any")\n@BenchmarkTools.benchmark test_any()\n\nprintln("union")\n@BenchmarkTools.benchmark test_arrUnion()\n\nprintln("number")\n@BenchmarkTools.benchmark test_arrNumber()\n\nprintln("real")\n@BenchmarkTools.benchmark test_arrReal()\n\nprintln("float")\n@BenchmarkTools.benchmark test_arrFloat()\n\n#= -------------------\n Output of the benchmarks\n -------------------\n=#\n\nnotypes\nBenchmarkTools.Trial: \n memory estimate: 921.56 KiB\n allocs estimate: 38979\n --------------\n minimum time: 855.070 \xce\xbcs (0.00% GC)\n median time: 1.006 ms (0.00% GC)\n mean time: 1.152 ms (12.60% GC)\n maximum time: 31.515 ms (91.59% GC)\n --------------\n samples: 4314\n evals/sample: 1\n\nany\nBenchmarkTools.Trial: \n memory estimate: 921.56 KiB\n allocs estimate: 38979\n --------------\n minimum time: 905.317 \xce\xbcs (0.00% GC)\n median time: 1.054 ms (0.00% GC)\n mean time: 1.197 ms (12.05% GC)\n maximum time: 30.355 ms (96.33% GC)\n --------------\n samples: 4152\n evals/sample: 1\n\nunion\nBenchmarkTools.Trial: \n memory estimate: 921.56 KiB\n allocs estimate: 38979\n --------------\n minimum time: 914.563 \xce\xbcs (0.00% GC)\n median time: 1.062 ms (0.00% GC)\n mean time: 1.210 ms (12.09% GC)\n maximum time: 32.472 ms (90.09% GC)\n --------------\n samples: 4111\n evals/sample: 1\n\nnumber\nBenchmarkTools.Trial: \n memory estimate: 921.56 KiB\n allocs estimate: 38979\n --------------\n minimum time: 926.189 \xce\xbcs (0.00% GC)\n median time: 1.110 ms (0.00% GC)\n mean time: 1.315 ms (14.18% GC)\n maximum time: 42.545 ms (97.21% GC)\n --------------\n samples: 3788\n evals/sample: 1\n\nreal\nBenchmarkTools.Trial: \n memory estimate: 921.56 KiB\n allocs estimate: 38979\n --------------\n minimum time: 863.699 \xce\xbcs (0.00% GC)\n median time: 1.015 ms (0.00% GC)\n mean time: 1.168 ms (12.70% GC)\n maximum time: 31.847 ms (96.50% GC)\n --------------\n samples: 4257\n evals/sample: 1\n\nfloat\nBenchmarkTools.Trial: \n memory estimate: 609.06 KiB\n allocs estimate: 28979\n --------------\n minimum time: 625.845 \xce\xbcs (0.00% GC)\n median time: 728.131 \xce\xbcs (0.00% GC)\n mean time: 829.031 \xce\xbcs (11.53% GC)\n maximum time: 30.811 ms (97.38% GC)\n --------------\n samples: 5989\n evals/sample: 1\n
Run Code Online (Sandbox Code Playgroud)\n
tho*_*oly 11
所有与性能相关的问题都有一个答案:类型注释可以提高结构的性能,但通常不会提高函数的性能。您从 Chris 那里读到的文章涉及数组(结构)的元素类型,尽管它是以函数可接受的类型的形式出现的。您应该在这种情况下解释它。
在 Julia 中,您应该对函数参数进行类型注释以控制调度,而不是为了性能。为什么?因为编译器将为您传递给它的每个具体类型专门化每个函数,从某种意义上说,它会自动生成您想要手动编写的所有那些专门化。因此添加类型注释的唯一原因是控制调用哪个方法:
is_this_a_number(x::Number) = true
is_this_a_number(x) = false
Run Code Online (Sandbox Code Playgroud)
结构则是另一回事。您可以在手册的性能提示部分阅读有关结构中类型注释的更多信息。
最后,请记住,自该问题提出之初以来,有些事情已经发生了变化。特别是,在许多情况下,联合分割Union
可以在具有较小具体类型的情况下提供良好的性能(isconcretetype
如果您不确定,请检查每个 )。
函数定义中的 N 是什么意思
数组中的维数。
归档时间: |
|
查看次数: |
365 次 |
最近记录: |