朱莉娅语言:多参数的效率

4
根据Julia手册的"性能技巧"部分,过多使用多重派发并不可取。我遇到了这样一种情况:似乎需要为我定义的类型使用3个参数。这与我的问题仅使用一个参数处理两种可能的类型有关。我意识到我可以通过使用另一个参数来解决那里提出的困难,但这样我的类型看起来就像
type mytype{R<:Real, S<:Any, T<:Any}
   x::Matrix{R}
   y::Dict{Int64, Vector{S}}
   z::Dict{T, Vector{Int64}}
end

这在性能方面是否不可取,因为有几个参数需要分派。在mytype上的函数将根据3个参数分派,函数参数正确吗?
2个回答

6

没问题。

类型上执行多重分派,您可以根据需要执行多少次。这就是它的用途。

但你不应该过度地在上进行多重分派。文档中的部分内容指出的就是这一点。您可以通过使用一个作为类型参数来实现这一点。

对值进行分派往往会导致动态分派的问题。这意味着调用具有值作为类型参数的函数的函数无法通过知道将要调用的函数来进行专门化。这与类型不稳定性密切相关。它可能会严重影响优化器,并使Julia像Python一样运行缓慢。

这里是我一部分代码的示例,其中在值上进行了过度的分派。它广泛使用Val{T}类型,该类型仅存在于允许在值上进行分派。它非常表现力强大,简洁明了,但是以这种方式编写的代码运行速度不如使用条件语句或字典查找的相同代码快。 (在这种情况下,这是我愿意接受的权衡)

文档还在指出,您不应该将值作为类型参数存储在自定义类型上。特别是如果您甚至不会对它们进行分派。这就是字段的用途。


好的,谢谢。我需要更多地了解这方面的细节(类型与值)。你有没有注意到这次我用了两个问题 ;) - mv3

5

可以的。注意,您可以这样编写:

type mytype{R<:Real, S, T}
   x::Matrix{R}
   y::Dict{Int64, Vector{S}}
   z::Dict{T, Vector{Int64}}
end

在大多数需要进行大量计算的情况下,严格的类型定义可以提升性能。如果你正在调用小函数(在许多情况下v0.5会自动进行内联调用,但是您可以通过@inline来帮助它),那么函数调用时没有性能损失,您也不必担心这个问题。
像往常一样,请进行基准测试并自行查看。这里最常见的问题通常出现在大量值类型的情况下。

2
过度规定参数或者"严格类型声明"通常不会提高性能:http://docs.julialang.org/en/latest/manual/performance-tips/#type-declarations。因为它可能使代码不够通用,所以通常不被鼓励。使用类型声明进行行为分发和结构声明,而不是性能优化。 - Isaiah Norton
2
在函数中,类型信息并不能帮助分派。因为类型是不同的:如果将它们全部设为“Any”,那么类型推断就无法正常工作。应该让函数松散地类型化,而让类型严格化。 - Chris Rackauckas
3
是的。该函数将自行专门针对给定的类型,因此 function(n::Int64) 将限制可以使用该函数的内容,但 function(n) 将派发并编译一个特定版本,以适用于 Int64 输入,因此在性能方面相同。 - Chris Rackauckas
1
@ChrisRackauckas 这真的很好知道,这是我以前不太理解的东西。我是Julia的新手(来自matlab、python和一点c++),到目前为止我真的很喜欢它,感谢你的所有帮助。 - mv3
1
请注意,function foo{R<:Real}(n::Vector{R}) 的性能要比function foo(n::Vector{Real})好得多。但是function bar(n::Real)function bar{R <: Real}(n :: R)相同。这就是@ChrisRackauckas提到的针对类型具体化的含义。 - Frames Catherine White
显示剩余5条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接