JuliaLang / julia

The Julia Programming Language
https://julialang.org/
MIT License
45.68k stars 5.48k forks source link

wriedlm writes Float32s in a way it cannot parse back #33904

Closed ViralBShah closed 4 years ago

ViralBShah commented 4 years ago

Circuitscape.jl tests pass (with 1 known error) on 1.3-rc5 and earlier releases. However on master (Julia Version 1.4.0-DEV.512 Commit 5516f40839 (2019-11-20 18:41 UTC)), I noticed more test failures. It seems like a regression.

https://github.com/Circuitscape/Circuitscape.jl/issues/202

This shouldn't have happened:

Raster One to All: Error During Test at /Users/viral/.julia/dev/Circuitscape/src/utils.jl:366
  Test threw exception
  Expression: compare_aagrid(r, x, tol)
  MethodError: no method matching compare_aagrid(::Array{Any,2}, ::Array{Float64,2}, ::Float64)
  Closest candidates are:
    compare_aagrid(::Array{T,2}, !Matched::Array{T,2}, ::Any) where T at /Users/viral/.julia/dev/Circuitscape/src/utils.jl:398
    compare_aagrid(::Array{T,2}, !Matched::Array{T,2}) where T at /Users/viral/.julia/dev/Circuitscape/src/utils.jl:398
  Stacktrace:
   [1] compare_all_output(::String, ::Bool) at /Users/viral/.julia/dev/Circuitscape/src/utils.jl:366
   [2] macro expansion at /Users/viral/.julia/dev/Circuitscape/src/utils.jl:330 [inlined]
   [3] macro expansion at /Users/viral/julia/usr/share/julia/stdlib/v1.4/Test/src/Test.jl:1110 [inlined]
   [4] macro expansion at /Users/viral/.julia/dev/Circuitscape/src/utils.jl:324 [inlined]
   [5] macro expansion at /Users/viral/julia/usr/share/julia/stdlib/v1.4/Test/src/Test.jl:1110 [inlined]
   [6] runtests(::typeof(compute_single)) at /Users/viral/.julia/dev/Circuitscape/src/utils.jl:260
Roger-luo commented 4 years ago

I'm not sure if it is the same issue (both seem to be macros), but tests fail for YaoBlocks as well on master (Julia Version 1.4.0-DEV.504 Commit 71c4d9bb19 (2019-11-20 10:27 UTC))

Test Summary:              | Pass  Fail  Total
test primitive block       |  245     2    247
  test constant gates      |   76     2     78
    test builtin gates     |   55           55
    matrix                 |   15           15
    test @const_gate       |    3     2      5
      bind new type        |    2     1      3
      define new           |    1     1      2
    I gate                 |    3            3
    test adjoints          |             No tests
  test phase gate          |   26           26
  test shift gate          |   25           25
  test rotation gate       |   33           33
  test time evolution      |   23           23
  test general matrix gate |   10           10
  test math gate           |   14           14
  test reflect gate        |    9            9
  test measure             |   28           28

for example

bind new type: Test Failed at /home/travis/build/QuantumBFS/YaoBlocks.jl/test/primitive/const_gate.jl:76
  Expression: #= /home/travis/build/QuantumBFS/YaoBlocks.jl/test/primitive/const_gate.jl:76 =# @allocated(mat(ComplexF32, XGate())) == 0
   Evaluated: 101372 == 0
Stacktrace:
 [1] top-level scope at /home/travis/build/QuantumBFS/YaoBlocks.jl/test/primitive/const_gate.jl:76
 [2] top-level scope at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.4/Test/src/Test.jl:1110
 [3] top-level scope at /home/travis/build/QuantumBFS/YaoBlocks.jl/test/primitive/const_gate.jl:73
 [4] top-level scope at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.4/Test/src/Test.jl:1110
 [5] top-level scope at /home/travis/build/QuantumBFS/YaoBlocks.jl/test/primitive/const_gate.jl:72
define new: Test Failed at /home/travis/build/QuantumBFS/YaoBlocks.jl/test/primitive/const_gate.jl:86
  Expression: #= /home/travis/build/QuantumBFS/YaoBlocks.jl/test/primitive/const_gate.jl:86 =# @allocated(mat(ComplexF32, TEST)) == 0
   Evaluated: 83390 == 0
Stacktrace:
 [1] top-level scope at /home/travis/build/QuantumBFS/YaoBlocks.jl/test/primitive/const_gate.jl:86
 [2] top-level scope at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.4/Test/src/Test.jl:1110
 [3] top-level scope at /home/travis/build/QuantumBFS/YaoBlocks.jl/test/primitive/const_gate.jl:80
 [4] top-level scope at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.4/Test/src/Test.jl:1110
 [5] top-level scope at /home/travis/build/QuantumBFS/YaoBlocks.jl/test/primitive/const_gate.jl:72

It seems master branch has a large extra allocation (which should be 0 on previous version)

KristofferC commented 4 years ago

What happens here is that the printing of a number in an output file changed to 4.8f-7. Exactly why this happens, I don't know (numerical change or numeric printing change due to the new Ryu printing algorithm?) This file is then read by readdlm but that cannot handle the f- format of Float32 so it reads that entry as a string:

typeof(read_aagrid("output/$(f)")) = Array{Any,2}
10×10 Array{Any,2}:
 2.0   "4.8f-7"  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0
 0.0  0.0        0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0
 2.0  0.0        0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0
 2.0  0.0        0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0
 2.0  0.0        0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0
 2.0  0.0        0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0
 2.0  0.0        0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0
 2.0  0.0        0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0
 2.0  0.0        0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0
 2.0  0.0        0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0[

Since the dlm file contained a "string", it gets inferred as Matrix{Any} and the compare_aagrid method no longer matches.

ViralBShah commented 4 years ago

Thanks for digging in @KristofferC.

ViralBShah commented 4 years ago

Should we close this issue then? Or is it useful to keep open for any other reason?

KristofferC commented 4 years ago

We should figure out why it happens. I'll try reduce it a bit and bisect.

KristofferC commented 4 years ago

Ok, the reason is that Julia (and writedlm) now prints Float32 numbers with the -f flag.

master

julia> print(1f-7)
1.0f-7

julia> a = rand(Float32, 2, 2) * Float32(0.0001);

julia> open("file_master.txt", "w") do io
           writedlm(io, a)
       end

julia> readdlm("file_master.txt")
2×2 Array{Any,2}:
 "6.7925306f-5"  "4.648714f-5"
 "4.6108566f-5"  "8.9852525f-5"

Note that these are strings

1.3

julia> print(1f-7)
1.0e-7

julia> a = rand(Float32, 2, 2) * Float32(0.0001);

julia> open("file_13.txt", "w") do io
           writedlm(io, a)
       end

julia> readdlm("file_13.txt")
2×2 Array{Float64,2}:
 1.07164e-5  8.09145e-5
 7.80861e-5  3.48754e-5

It doesn't seem correct to me that writedlm writes numbers in a format that it then cannot parse back.

CC @quinnj, @simonbyrne.