为什么Float64操作比Float16快?



我想知道为什么操作Float64值比操作Float16快:

julia> rnd64 = rand(Float64, 1000);
julia> rnd16 = rand(Float16, 1000);
julia> @benchmark rnd64.^2
BenchmarkTools.Trial: 10000 samples with 10 evaluations.
Range (min … max):  1.800 μs … 662.140 μs  ┊ GC (min … max):  0.00% … 99.37%
Time  (median):     2.180 μs               ┊ GC (median):     0.00%
Time  (mean ± σ):   3.457 μs ±  13.176 μs  ┊ GC (mean ± σ):  12.34% ±  3.89%
▁██▄▂▂▆▆▄▂▁ ▂▆▄▁                                     ▂▂▂▁   ▂
████████████████▇▇▆▆▇▆▅▇██▆▆▅▅▆▄▄▁▁▃▃▁▁▄▁▃▄▁▃▁▄▃▁▁▆▇██████▇ █
1.8 μs       Histogram: log(frequency) by time      10.6 μs <
Memory estimate: 8.02 KiB, allocs estimate: 5.
julia> @benchmark rnd16.^2
BenchmarkTools.Trial: 10000 samples with 6 evaluations.
Range (min … max):  5.117 μs … 587.133 μs  ┊ GC (min … max): 0.00% … 98.61%
Time  (median):     5.383 μs               ┊ GC (median):    0.00%
Time  (mean ± σ):   5.716 μs ±   9.987 μs  ┊ GC (mean ± σ):  3.01% ±  1.71%
▃▅█▇▅▄▄▆▇▅▄▁             ▁                                ▂
▄██████████████▇▆▇▆▆▇▆▇▅█▇████▇█▇▇▆▅▆▄▇▇▆█▇██▇█▇▇▇▆▇▇▆▆▆▆▄▄ █
5.12 μs      Histogram: log(frequency) by time      7.48 μs <
Memory estimate: 2.14 KiB, allocs estimate: 5.

也许你会问为什么我期望相反:因为Float16值具有更少的浮点精度:

julia> rnd16[1]
Float16(0.627)
julia> rnd64[1]
0.4375452455597999

精度越低的计算不应该进行得越快吗?那么我想知道为什么有人要用Float16?他们甚至可以用Float128!

正如您所看到的,您期望的效果已经出现在Float32:

julia> rnd64 = rand(Float64, 1000);
julia> rnd32 = rand(Float32, 1000);
julia> rnd16 = rand(Float16, 1000);
julia> @btime $rnd64.^2;
616.495 ns (1 allocation: 7.94 KiB)
julia> @btime $rnd32.^2;
330.769 ns (1 allocation: 4.06 KiB)  # faster!!
julia> @btime $rnd16.^2;
2.067 μs (1 allocation: 2.06 KiB)  # slower!!

Float64Float32在大多数平台上都有硬件支持,但Float16没有,因此必须在软件中实现。

还请注意,在微基准测试时应该使用变量插值($)。这里的区别很明显,尤其是在分配方面:

julia> @btime $rnd32.^2;
336.187 ns (1 allocation: 4.06 KiB)
julia> @btime rnd32.^2;
930.000 ns (5 allocations: 4.14 KiB)

简短的回答是,除非你使用GPU或苹果CPU,否则你可能不应该使用Float16,因为(截至2022年)其他处理器不支持Float16的硬件。

最新更新