Julia语言中的Generic Float类型?

时间:2017-06-23 20:20:55

标签: types julia

我的问题很简单,julia中是否有通用Float类型?例如,对于Integer s的情况,可以简单地编写Int,它将在32位系统中翻译为Int32或在64位系统中翻译为Int64 。但是对于Float s,请参阅下面的示例函数:

function bb(n)
    b = Array{Float64}(n) 
    b[1] = 0.9999
    for i = 2:n
        @inbounds b[i] = b[i-1] * 0.9999
    end    
    println(b[n])
end

bb(10^3)
@time bb(10^3)
@time bb(10^8)

它提供以下时序结果以及总内存分配:

0.9048328935585562
0.9048328935585562
  0.000100 seconds (135 allocations: 15.750 KB)
2.4703e-320
  3.230642 seconds (14 allocations: 762.940 MB, 1.51% gc time)

现在将第一行更改为b = Array{AbstractFloat}(n)并查看非常庞大的时间和内存分配:

0.9048328935585562
0.9048328935585562
  0.003564 seconds (2.13 k allocations: 46.953 KB)
2.4703e-320
  351.068176 seconds (200.00 M allocations: 3.725 GB, 0.74% gc time)

我无法使用b = Array{Float}(n),我提出的唯一解决方案就是这种非优雅的符号b = Array{typeof(1.0)}(n)

1 个答案:

答案 0 :(得分:8)

Abstract Float的问题与32位或64位无关。

Julia没有匹配Float的{​​{1}},因为 浮点文字总是 Float64 即在64位或32位系统Int上。 (对于typeof(1.0)==Float64字面用法Float32

如果您真的想要一个,则需要将其定义为

1.0f0

但这似乎没用,因为它不会对应任何东西。 它不会是一个更接近硬件的地图,即使因为在CPU中实现浮点数学,通常是64位,即使在32位CPU上也是如此。

请参阅:this thread on DiscourseFloat type like Int type

在32位系统上使用Float32和在64位系统上使用Float64没有任何优势。 在任何地方使用Float32都有好处 - 如果你不需要准确性 - 关键的一个是减少内存分配 - 将分配时间减半,以及花费在进程间通信上的时间。

关于您的性能问题:

@static if Sys.WORDSIZE == 64 const Float = Float64 else const Float = Float32 end 的糟糕表现 是因为您正在创建一个包含抽象类型的容器。 见performance tips: Avoid Containers with Abstract type parameters 这些都很慢,因为它们基本上是指针数组 - 每次元素与之交互时都需要取消引用指针。 这是因为已声明此类数组b = Array{AbstractFloat}(n)可能包含任意数量的不同类型的元素。有些可能是b其他人可能是Float16,有些甚至可能是Float32BigFloat。 因此,包含抽象类型的容器使用起来很慢,因为它们是指针数组。

所以写ArbFloat{221}完全等同于写b = Array{typeof(1.0)}(n) 那里什么也没做。 所以这显然不能解决你的真正问题。

假设您的真正问题是您想要指定返回的类型,那么您应该将其作为参数传递:

b = Array{Float64}(n)

使用(例如)function bb(T, n) b = Array{T}(n) b[1] = 0.9999 for i = 2:n @inbounds b[i] = b[i-1] * 0.9999 end println(b[n]) end 调用它。 所有的数学运算都发生在Float64中,因为它是使用Float64文字指定的,但是当你将它分配给数组时,将会隐含地调用bb(Float32, 100)

或者,您可能希望传递值,并推断出类型:

convert(T,...)

通过以下方式调用:function bb(n, b1::T) b = Array{T}(n) b[1] = b1 for i = 2:n @inbounds b[i] = b[i-1] * b1 end println(b[n]) end