Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Creating a system image fails in Julia 1.10.0-beta2 while it works with 1.9 #50729

Closed
ufechner7 opened this issue Jul 30, 2023 · 49 comments
Closed
Labels
kind:regression Regression in behavior compared to a previous version

Comments

@ufechner7
Copy link

ufechner7 commented Jul 30, 2023

On Ubuntu Linux version 20.04 with 16GB physical RAM creating a system image using package compiler fails badly when using Julia 1.10. The problem is that the system runs out of memory. With "fails badly" I mean that my laptop gets stuck, the OOM killer is not getting activated. Probably the memory usage rises too fast for the OOM killer.

This should not happen. Before starting the multi-threaded system image creation Julia should check the available free RAM (including the swap file) and if less than 6GB are free it should only start one thread. Alternatively there could be a command line option that determines the number of threads to use.

I use the following script to create a system image:

using Pkg

@info "Loading packages ..."
using ModelingToolkit, OrdinaryDiffEq, DataInterpolations, LaTeXStrings, Timers, 
      PackageCompiler, ControlSystemsBase, Roots, JLD2, YAML, DataFrames, MAT, EnumX,
      FFTW, Revise

PackageCompiler.create_sysimage(
    [:ModelingToolkit, :OrdinaryDiffEq, :DataInterpolations, :LaTeXStrings, :Timers,
     :ControlSystemsBase, :Roots, :JLD2, :YAML, :DataFrames, :MAT, :EnumX, :FFTW, :Revise];
    sysimage_path="kps-image_tmp.so",
    precompile_execution_file=joinpath("test", "test_for_precompile.jl")
)
@vchuravy vchuravy added this to the 1.10 milestone Jul 30, 2023
@vchuravy
Copy link
Sponsor Member

Cc: @pchintalapudi

@pchintalapudi
Copy link
Member

What's the versioninfo() for the system?

Before starting the multi-threaded system image creation Julia should check the available free RAM (including the swap file) and if less than 6GB are free it should only start one thread.

This 6GB number is going to vary by size of system image and number of threads (2 threads might not exceed that for even larger images). There is always the escape hatch where you cut it down to one thread (set the JULIA_IMAGE_THREADS=N environment variable).

@ufechner7
Copy link
Author

ufechner7 commented Jul 30, 2023

What's the versioninfo() for the system?

julia> versioninfo()
Julia Version 1.10.0-beta1
Commit 6616549950e (2023-07-25 17:43 UTC)
Platform Info:
  OS: Linux (x86_64-linux-gnu)
  CPU: 8 × Intel(R) Core(TM) i7-10510U CPU @ 1.80GHz
  WORD_SIZE: 64
  LIBM: libopenlibm
  LLVM: libLLVM-15.0.7 (ORCJIT, skylake)
  Threads: 1 on 8 virtual cores

RAM usage Julia 1.9.2: 10GB
Julia 1.10.9-beta1: 24 GB

Strange: Julia 1.10 needs 24 GB on a 4 core CPU, but also on a 16 core CPU.

@pchintalapudi
Copy link
Member

Does it work when set with one thread? (JULIA_IMAGE_THREADS=1)

@ufechner7
Copy link
Author

ufechner7 commented Jul 30, 2023

Does it work when set with one thread? (JULIA_IMAGE_THREADS=1)

Yes, after adding a GC.gc() at the end of the test_for_precompile.jl script. With 1 thread 1.10 needs 12.7 GB, while 1.9 needs only 10.1GB.

So we have two issues:

  • Julia 1.10.0-beta1 needs 1.3 times the RAM for building a sysimage with one thread
  • it uses multiple threads by default and then needs 2.4 times the RAM

with 2, 4 and 16 threads it always needs 24GB RAM.

@pchintalapudi
Copy link
Member

pchintalapudi commented Jul 30, 2023

With or without multithreading? --heap-size-hint may be helpful here if the reduction is that steep.

@ufechner7
Copy link
Author

With or without multithreading? --heap-size-hint may be helpful here if the reduction is that steep.

Without multithreading the needed size is 12.7 GB, worse than with Julia 1.9.2 which needs 10.1GB, but good enough to be able to build the image with 16GB RAM.

And no, --heap-size-hint has no effect, but that is another bug: #50658

@MariusDrulea
Copy link

Same behavior in Windows 10. Works with 1.9, but fails with 1.10.0-beta1.

using PackageCompiler

PackageCompiler.create_sysimage(
    [:GLMakie];
    sysimage_path="C:\\temp\\sys_image_sample.so",
    precompile_execution_file=joinpath(@__DIR__, "precompile.jl")
)

precompile.jl

using GLMakie

The error:

[ Info: PackageCompiler: Done
✔ [02m:53s] PackageCompiler: compiling incremental system image
D:/z_installed_programs/julia-depot/artifacts/fdff308295487f361ef6e8dc2d27f5abe8a6eee9/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/8.1.0/../../../../x86_64-w64-mingw32/bin/ld.exe: 
Error: export ordinal too large: 98037
collect2.exe: error: ld returned 1 exit status
ERROR: LoadError: failed process: Process(setenv(`'D:\z_installed_programs\julia-depot\artifacts\fdff308295487f361ef6e8dc2d27f5abe8a6eee9\mingw64\bin\g++.exe' -m64 -march=x86-64 -shared '-LD:\z_installed_programs\julia-depot\juliaup\julia-1.10.0-beta1+0.x64.w64.mingw32\bin' '-LD:\z_installed_programs\julia-depot\juliaup\julia-1.10.0-beta1+0.x64.w64.mingw32\bin' -o 'C:\temp\sys_image_sample.so' -Wl,--whole-archive 'C:\Users\someuser\AppData\Local\Temp\jl_X65etsvar4.o' -Wl,--no-whole-archive -ljulia -ljulia-internal -lopenlibm -Wl,--export-all-symbols`,["CLEARCASE_GROUPS=DE\\ISM_CC_USER_GW;DE\\ism_clearcase_all_lc;DE\\ism_cc_cssim_lc;DE\\ism_cc_mtc_lc;DE\\ism_cc_snsecs_test_lc;DE\\cceam3associates;DE\\Domain Users", "WINDIR=C:\\WINDOWS", "PATH=C:\\Program Files\\Git\\mingw64\\bin;C:\\Program Files\\Git\\usr\\local\\bin;C:\\Program Files\\Git\\usr\\bin;C:\\Program Files (x86)\\Microsoft SDKs\\Azure\\CLI2\\wbin;C:\\tools\\Anaconda3;C:\\tools\\Anaconda3\\Library\\mingw-w64\\bin;C:\\tools\\Anaconda3\\Library\\usr\\bin;C:\\tools\\Anaconda3\\Library\\bin;C:\\tools\\Anaconda3\\Scripts;C:\\WINDOWS\\system32;C:\\WINDOWS;C:\\WINDOWS\\System32\\Wbem;C:\\Program Files\\RedHat\\java-1.8.0-openjdk\\missioncontrol\\;C:\\Program Files\\RedHat\\java-1.8.0-openjdk\\webstart\\;C:\\Program Files\\RedHat\\java-1.8.0-openjdk\\bin;C:\\Program Files\\RedHat\\java-1.8.0-openjdk\\jre\\bin;C:\\WINDOWS\\System32\\WindowsPowerShell\\v1.0;C:\\WINDOWS\\System32\\OpenSSH;C:\\Program Files\\RedHat\\java-1.8.0-openjdk\\missioncontrol;C:\\Oracle\\Client32\\bin;C:\\Program Files\\7-Zip;C:\\Program Files\\Microsoft SQL Server\\130\\Tools\\Binn;C:\\Program Files\\Microsoft SQL Server\\Client SDK\\ODBC\\170\\Tools\\Binn;C:\\Program Files\\Git\\cmd;C:\\Program Files\\Git\\;C:\\Program Files\\Calibre2;C:\\Program Files\\CMake\\bin;C:\\tools\\mingw64\\bin;C:\\Users\\someuser\\.dnx\\bin;C:\\Program Files\\Microsoft DNX\\Dnvm;C:\\Program Files\\Microsoft SQL Server\\120\\Tools\\Binn;C:\\Program Files (x86)\\dotnet;C:\\Users\\someuser\\AppData\\Local\\Microsoft\\WindowsApps;C:\\Program Files\\Git\\usr\\bin\\vendor_perl;C:\\Program Files\\Git\\usr\\bin\\core_perl;C:\\Program Files\\dotnet\\;C:\\texlive\\2022\\bin\\win32;C:\\Program Files\\NVIDIA Corporation\\cuDNN\\v8.1.1\\bin;c:\\TCC\\Base\\StartBTC\\startBTC;c:\\TCC\\itc2;C:\\Program Files (x86)\\RedHat\\java-1.8.0-openjdk\\webstart\\;C:\\Program Files (x86)\\RedHat\\java-1.8.0-openjdk\\bin;C:\\Program Files (x86)\\RedHat\\java-1.8.0-openjdk\\jre\\bin;C:\\WINDOWS\\System32\\WindowsPowerShell\\v1.0\\;C:\\Program Files\\Graphviz\\bin;C:\\Program Files\\Microsoft VS Code\\bin;C:\\Users\\someuser\\AppData\\Local\\Microsoft\\WindowsApps;c:\\batch;c:\\tools;;D:\\z_installed_programs\\julia-depot\\artifacts\\fdff308295487f361ef6e8dc2d27f5abe8a6eee9\\mingw64\\bin", "USERDOMAIN_ROAMINGPROFILE=EMEA", "REDHAT_JAVA_HOME=C:\\Program Files\\RedHat\\java-1.8.0-openjdk\\", "NEXTHINK=C:\\Program Files\\Nexthink\\Collector", "SNC_LIB_32=C:\\Program Files (x86)\\SAP\\FrontEnd\\SecureLogin\\lib\\sapcrypto.dll", "LOCALAPPDATA=C:\\Users\\someuser\\AppData\\Local", "MOZ_LEGACY_PROFILES=1", "HOMEPATH=\\Users\\someuser"  …  "FPS_BROWSER_APP_PROFILE_STRING=Internet Explorer", "SSF_LIBRARY_PATH_64=C:\\Program Files\\SAP\\FrontEnd\\SecureLogin\\lib\\sapcrypto.dll", "PROGRAMW6432=C:\\Program Files", "HOME=C:\\Users\\someuser", "HTTPS_PROXY=http://127.0.0.1:3128", "HOMEDRIVE=C:", "OPENBLAS_MAIN_FREE=1", "PROCESSOR_ARCHITECTURE=AMD64", "TEMP=C:\\Users\\someuser\\AppData\\Local\\Temp", "COLORTERM=truecolor"]), ProcessExited(1)) [1]

Stacktrace:
 [1] pipeline_error
   @ Base .\process.jl:565 [inlined]
 [2] run(::Cmd; wait::Bool)
   @ Base .\process.jl:480
 [3] run
   @ PackageCompiler .\process.jl:477 [inlined]
 [4] run_compiler(cmd::Cmd; cplusplus::Bool)
   @ PackageCompiler D:\z_installed_programs\julia-depot\packages\PackageCompiler\b2smD\src\PackageCompiler.jl:194
 [5] run_compiler
   @ PackageCompiler D:\z_installed_programs\julia-depot\packages\PackageCompiler\b2smD\src\PackageCompiler.jl:190 [inlined]
 [6] create_sysimg_from_object_file(object_files::Vector{…}, sysimage_path::String; version::Nothing, compat_level::String, soname::Nothing)
   @ PackageCompiler D:\z_installed_programs\julia-depot\packages\PackageCompiler\b2smD\src\PackageCompiler.jl:634
 [7] create_sysimg_from_object_file
   @ PackageCompiler D:\z_installed_programs\julia-depot\packages\PackageCompiler\b2smD\src\PackageCompiler.jl:620 [inlined]
 [8] create_sysimage(packages::Vector{…}; sysimage_path::String, project::String, precompile_execution_file::String, precompile_statements_file::Vector{…}, incremental::Bool, filter_stdlibs::Bool, cpu_target::String, script::Nothing, sysimage_build_args::Cmd, include_transitive_dependencies::Bool, base_sysimage::Nothing, julia_init_c_file::Nothing, version::Nothing, soname::Nothing, compat_level::String, extra_precompiles::String)
   @ PackageCompiler D:\z_installed_programs\julia-depot\packages\PackageCompiler\b2smD\src\PackageCompiler.jl:600
 [9] top-level scope
   @ D:\z_installed_programs\julia-depot\dev\mypackage.jl_1.10\src\training\sysimage\how2sysimage.jl:3
Some type information was truncated. Use `show(err)` to see complete types.
in expression starting at D:\z_installed_programs\julia-depot\dev\mypackage.jl_1.10\src\training\sysimage\how2sysimage.jl:3

@pchintalapudi
Copy link
Member

That is a different issue, happening during linking rather than out of memory.

Error: export ordinal too large: 98037
collect2.exe: error: ld returned 1 exit status

This is probably related to us using external hidden symbols to link across compilation units in multithreaded image generation.

@vtjnash
Copy link
Sponsor Member

vtjnash commented Aug 1, 2023

Why are there many exports? There should only be a small handful

@pchintalapudi
Copy link
Member

Maybe windows ld counts external hidden symbols as exports?

@pchintalapudi
Copy link
Member

@MariusDrulea can you check if your issue still happens on #50791 with JULIA_IMAGE_THREADS=1?

@brenhinkeller brenhinkeller added the kind:regression Regression in behavior compared to a previous version label Aug 5, 2023
@MariusDrulea
Copy link

MariusDrulea commented Aug 9, 2023

@MariusDrulea can you check if your issue still happens on #50791 with JULIA_IMAGE_THREADS=1?

I noticed the PR got merged into the main branch.
@pchintalapudi maybe you meant the #50752 PR?

@MariusDrulea
Copy link

MariusDrulea commented Aug 9, 2023

I wonder how to easily test PR builds. One way to deal with this is to rename the julia-commit folder to julia-1.10.0-beta1+0.x64.w64.mingw32. This way I can test any PR. While ok-ish, is there a more direct way to do it in juliaup?
image

@MariusDrulea
Copy link

MariusDrulea commented Aug 9, 2023

Here is the test for #50752. Still fails. Note I haven't set JULIA_IMAGE_THREADS=1.

Note the number of globals. The package compiler has other globals than what you count with this line of code: https://github.com/JuliaLang/julia/pull/50752/files#diff-dcb7645cc96941c621f6aeaaebbdcdd54e83fe925eed0135e4fd840806fb4d91R937

Externalized 386 / 460(8.391304e-01) globals
PackageCompiler: compiling incremental system imageExternalized 69110 / 110102(6.276907e-01) globals

Full console output:

PS D:\z_installed_programs\julia-depot\dev\mtdnn_base.jl_1.10> julia --project=.
               _
   _       _ _(_)_     |  Documentation: https://docs.julialang.org
  (_)     | (_) (_)    |
   _ _   _| |_  __ _   |  Type "?" for help, "]?" for Pkg help.
  | | | | | | |/ _` |  |
  | | |_| | | | (_| |  |  Version 1.11.0-DEV.231 (2023-08-07)
 _/ |\__'_|_|_|\__'_|  |  pc/internalize/fb0bc12ffb (fork: 2 commits, 5 days)
|__/  

julia> include("./src/training\\sysimage\\how2sysimage.jl")
Externalized 386 / 460(8.391304e-01) globals
Precompiling project...
  143 dependencies successfully precompiled in 184 seconds. 318 already precompiled.
  1 dependency had warnings during precompilation:
┌ ImageSegmentation [80713f31-8817-5129-9cf8-209ff8fb23e1]
│  [pid 32484] waiting for IO to finish:
│   TYPE[FD/PID]       @UV_HANDLE_T->DATA
│   timer              @00000243fa512ab0->00000243858109d0
└  
[ Info: PackageCompiler: Executing D:\z_installed_programs\julia-depot\dev\mypackage.jl_1.10\src\training\sysimage\precompile.jl => C:\Users\someuser\AppData\Local\Temp\jl_packagecompiler_UPI2zv\jl_4C23.tmp
[ Info: PackageCompiler: Done
⣠ [00m:54s] PackageCompiler: compiling incremental system imageExternalized 69110 / 110102(6.276907e-01) globals
✔ [02m:19s] PackageCompiler: compiling incremental system image
D:/z_installed_programs/julia-depot/artifacts/fdff308295487f361ef6e8dc2d27f5abe8a6eee9/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/8.1.0/../../../../x86_64-w64-mingw32/bin/ld.exe: 
Error: export ordinal too large: 69175
collect2.exe: error: ld returned 1 exit status
ERROR: LoadError: failed process: Process(setenv(`'D:\z_installed_programs\julia-depot\artifacts\fdff308295487f361ef6e8dc2d27f5abe8a6eee9\mingw64\bin\g++.exe' -m64 -march=x86-64 -shared '-LD:\z_installed_programs\julia-depot\juliaup\julia-1.10.0-beta1+0.x64.w64.mingw32\bin' '-LD:\z_installed_programs\julia-depot\juliaup\julia-1.10.0-beta1+0.x64.w64.mingw32\bin' -o 'C:\temp\sys_image_sample.so' -Wl,--whole-archive 'C:\Users\someuser\AppData\Local\Temp\jl_obuHURQLyp.o' -Wl,--no-whole-archive -ljulia -ljulia-internal -lopenlibm -Wl,--export-all-symbols`,["CLEARCASE_GROUPS=DE\\ISM_CC_USER_GW;DE\\ism_clearcase_all_lc;DE\\ism_cc_cssim_lc;DE\\ism_cc_mtc_lc;DE\\ism_cc_snsecs_test_lc;DE\\cceam3associates;DE\\Domain Users", "WINDIR=C:\\WINDOWS", "PATH=C:\\Program Files\\Git\\mingw64\\bin;C:\\Program Files\\Git\\usr\\local\\bin;C:\\Program Files\\Git\\usr\\bin;C:\\Program Files (x86)\\Microsoft SDKs\\Azure\\CLI2\\wbin;C:\\tools\\Anaconda3;C:\\tools\\Anaconda3\\Library\\mingw-w64\\bin;C:\\tools\\Anaconda3\\Library\\usr\\bin;C:\\tools\\Anaconda3\\Library\\bin;C:\\tools\\Anaconda3\\Scripts;C:\\WINDOWS\\system32;C:\\WINDOWS;C:\\WINDOWS\\System32\\Wbem;C:\\Program Files\\RedHat\\java-1.8.0-openjdk\\missioncontrol\\;C:\\Program Files\\RedHat\\java-1.8.0-openjdk\\webstart\\;C:\\Program Files\\RedHat\\java-1.8.0-openjdk\\bin;C:\\Program Files\\RedHat\\java-1.8.0-openjdk\\jre\\bin;C:\\WINDOWS\\System32\\WindowsPowerShell\\v1.0;C:\\WINDOWS\\System32\\OpenSSH;C:\\Program Files\\RedHat\\java-1.8.0-openjdk\\missioncontrol;C:\\Oracle\\Client32\\bin;C:\\Program Files\\7-Zip;C:\\Program Files\\Microsoft SQL Server\\130\\Tools\\Binn;C:\\Program Files\\Microsoft SQL Server\\Client SDK\\ODBC\\170\\Tools\\Binn;C:\\Program Files\\Git\\cmd;C:\\Program Files\\Git\\;C:\\Program 
Files\\Calibre2;C:\\Program Files\\CMake\\bin;C:\\tools\\mingw64\\bin;C:\\Users\\someuser\\.dnx\\bin;C:\\Program Files\\Microsoft DNX\\Dnvm;C:\\Program Files\\Microsoft SQL Server\\120\\Tools\\Binn;C:\\Program Files (x86)\\dotnet;C:\\Users\\someuser\\AppData\\Local\\Microsoft\\WindowsApps;C:\\Program Files\\Git\\usr\\bin\\vendor_perl;C:\\Program Files\\Git\\usr\\bin\\core_perl;C:\\Program Files\\dotnet\\;C:\\texlive\\2022\\bin\\win32;C:\\Program Files\\NVIDIA Corporation\\cuDNN\\v8.1.1\\bin;c:\\TCC\\Base\\StartBTC\\startBTC;c:\\TCC\\itc2;C:\\Program Files (x86)\\RedHat\\java-1.8.0-openjdk\\webstart\\;C:\\Program Files (x86)\\RedHat\\java-1.8.0-openjdk\\bin;C:\\Program Files (x86)\\RedHat\\java-1.8.0-openjdk\\jre\\bin;C:\\WINDOWS\\System32\\WindowsPowerShell\\v1.0\\;C:\\Program Files\\Graphviz\\bin;C:\\Program Files\\Microsoft VS Code\\bin;C:\\Users\\someuser\\AppData\\Local\\Microsoft\\WindowsApps;c:\\batch;c:\\tools;;D:\\z_installed_programs\\julia-depot\\artifacts\\fdff308295487f361ef6e8dc2d27f5abe8a6eee9\\mingw64\\bin", "USERDOMAIN_ROAMINGPROFILE=EMEA", "REDHAT_JAVA_HOME=C:\\Program Files\\RedHat\\java-1.8.0-openjdk\\", "NEXTHINK=C:\\Program Files\\Nexthink\\Collector", "SNC_LIB_32=C:\\Program Files (x86)\\SAP\\FrontEnd\\SecureLogin\\lib\\sapcrypto.dll", "LOCALAPPDATA=C:\\Users\\someuser\\AppData\\Local", "MOZ_LEGACY_PROFILES=1", "HOMEPATH=\\Users\\someuser" 
 …  "FPS_BROWSER_APP_PROFILE_STRING=Internet Explorer", "SSF_LIBRARY_PATH_64=C:\\Program Files\\SAP\\FrontEnd\\SecureLogin\\lib\\sapcrypto.dll", "PROGRAMW6432=C:\\Program Files", "HOME=C:\\Users\\someuser", "HTTPS_PROXY=http://127.0.0.1:3128", "HOMEDRIVE=C:", "OPENBLAS_MAIN_FREE=1", "PROCESSOR_ARCHITECTURE=AMD64", "TEMP=C:\\Users\\someuser\\AppData\\Local\\Temp", "COLORTERM=truecolor"]), ProcessExited(1)) [1]

Stacktrace:
  [1] pipeline_error
    @ Base .\process.jl:565 [inlined]
  [2] run(::Cmd; wait::Bool)
    @ Base .\process.jl:480
  [3] run
    @ PackageCompiler .\process.jl:477 [inlined]
  [4] run_compiler(cmd::Cmd; cplusplus::Bool)
    @ PackageCompiler D:\z_installed_programs\julia-depot\packages\PackageCompiler\b2smD\src\PackageCompiler.jl:194
  [5] run_compiler
    @ PackageCompiler D:\z_installed_programs\julia-depot\packages\PackageCompiler\b2smD\src\PackageCompiler.jl:190 [inlined]
  [6] create_sysimg_from_object_file(object_files::Vector{String}, sysimage_path::String; version::Nothing, compat_level::String, soname::Nothing)
    @ PackageCompiler D:\z_installed_programs\julia-depot\packages\PackageCompiler\b2smD\src\PackageCompiler.jl:634
  [7] create_sysimg_from_object_file
    @ PackageCompiler D:\z_installed_programs\julia-depot\packages\PackageCompiler\b2smD\src\PackageCompiler.jl:620 [inlined]
  [8] create_sysimage(packages::Vector{…}; sysimage_path::String, project::String, precompile_execution_file::String, precompile_statements_file::Vector{…}, incremental::Bool, filter_stdlibs::Bool, cpu_target::String, script::Nothing, sysimage_build_args::Cmd, include_transitive_dependencies::Bool, base_sysimage::Nothing, julia_init_c_file::Nothing, version::Nothing, soname::Nothing, compat_level::String, extra_precompiles::String)
    @ PackageCompiler D:\z_installed_programs\julia-depot\packages\PackageCompiler\b2smD\src\PackageCompiler.jl:600
  [9] top-level scope
    @ D:\z_installed_programs\julia-depot\dev\mypackage.jl_1.10\src\training\sysimage\how2sysimage.jl:3
 [10] include(fname::String)
    @ Base.MainInclude .\client.jl:489
 [11] top-level scope
    @ REPL[3]:1
in expression starting at D:\z_installed_programs\julia-depot\dev\mypackage.jl_1.10\src\training\sysimage\how2sysimage.jl:3
Some type information was truncated. Use `show(err)` to see complete types.

@MariusDrulea
Copy link

I set up the JULIA_IMAGE_THREADS=1. The issue still persist for #50752

PS D:\z_installed_programs\julia-depot\dev\mypackage.jl_1.10> $env:JULIA_NUM_THREADS = 1
PS D:\z_installed_programs\julia-depot\dev\mypackage.jl_1.10> $env:JULIA_NUM_THREADS    
1
PS D:\z_installed_programs\julia-depot\dev\mypackage.jl_1.10> julia
               _
   _       _ _(_)_     |  Documentation: https://docs.julialang.org
  (_)     | (_) (_)    |
   _ _   _| |_  __ _   |  Type "?" for help, "]?" for Pkg help.
  | | | | | | |/ _` |  |
  | | |_| | | | (_| |  |  Version 1.11.0-DEV.231 (2023-08-07)
|__/                   |

julia> versioninfo()
Julia Version 1.11.0-DEV.231
Commit fb0bc12ffb (2023-08-07 22:52 UTC)
Build Info:
  Official https://julialang.org/ release
Platform Info:
  OS: Windows (x86_64-w64-mingw32)
  CPU: 12 × Intel(R) Core(TM) i7-10850H CPU @ 2.70GHz
  WORD_SIZE: 64
  LIBM: libopenlibm
  LLVM: libLLVM-15.0.7 (ORCJIT, skylake)
  Threads: 1 on 12 virtual cores
Environment:
  JULIA_DEPOT_PATH = D:\z_installed_programs\julia-depot
  JULIA_NUM_THREADS = 1

julia> exit()

PS D:\z_installed_programs\julia-depot\dev\mypackage.jl_1.10> julia --project=. .\src\training\sysimage\how2sysimage.jl
[ Info: PackageCompiler: Executing D:\z_installed_programs\julia-depot\dev\mypackage.jl_1.10\src\training\sysimage\precompile.jl => C:\Users\ddr5clj\AppData\Local\Temp\jl_packagecompiler_6FcFNG\jl_3A0F.tmp
[ Info: PackageCompiler: Done
⡆ [00m:51s] PackageCompiler: compiling incremental system imageExternalized 69152 / 110102(6.280722e-01) globals
✔ [02m:15s] PackageCompiler: compiling incremental system image
D:/z_installed_programs/julia-depot/artifacts/fdff308295487f361ef6e8dc2d27f5abe8a6eee9/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/8.1.0/../../../../x86_64-w64-mingw32/bin/ld.exe: 
Error: export ordinal too large: 69217
collect2.exe: error: ld returned 1 exit status

@MariusDrulea
Copy link

MariusDrulea commented Aug 9, 2023

@pchintalapudi I have also tested #50791 with JULIA_NUM_THREADS=1. Unfortunately the error is still there. As you can see, the number of exports nearly doubled.

  | | |_| | | | (_| |  |  Version 1.11.0-DEV.230 (2023-08-04)
 _/ |\__'_|_|_|\__'_|  |  pc/internal-create-native/a4657c81e9 (fork: 1 commits, 5 days)

✔ [02m:23s] PackageCompiler: compiling incremental system image
D:/z_installed_programs/julia-depot/artifacts/fdff308295487f361ef6e8dc2d27f5abe8a6eee9/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/8.1.0/../../../../x86_64-w64-mingw32/bin/ld.exe: 
Error: export ordinal too large: 110170

@pchintalapudi
Copy link
Member

It needs to be with JULIA_IMAGE_THREADS=1, not JULIA_NUM_THREADS.

@MariusDrulea
Copy link

MariusDrulea commented Aug 9, 2023

Update:
#50752 indeed works with JULIA_IMAGE_THREADS=1. If I don't set this env_variable, it fails.
1.10.0-beta1 does not work with JULIA_IMAGE_THREADS=1

@pchintalapudi
Copy link
Member

#50791 is the change that makes JULIA_IMAGE_THREADS=1 work for your case, and it's marked for backport, so it'll get in before 1.10 is released (unsure if it'll make it into beta2).

@MariusDrulea
Copy link

MariusDrulea commented Aug 9, 2023

#50752 works, this is the PR I have tested. Isn't this expected?

@pchintalapudi
Copy link
Member

Yes, but #50752 is based off #50791, which has the actual change for JULIA_IMAGE_THREADS=1 here. As noted, without JULIA_IMAGE_THREADS=1 #50752 isn't helping your case enough.

@MariusDrulea
Copy link

This #50874 works just fine on my Windows machine.

@MariusDrulea
Copy link

MariusDrulea commented Aug 11, 2023

I wonder how to easily test PR builds. One way to deal with this is to rename the julia-commit folder to julia-1.10.0-beta1+0.x64.w64.mingw32. This way I can test any PR. While ok-ish, is there a more direct way to do it in juliaup?

To answer my own question, I just have to copy the binaries of some commit into the juliaup folder for example.
Then juliaup link 590a63b299 .\julia-590a63b299\bin\julia.exe will create the 590a63b299 channel to our desired julia binary. A different channel name can be used. Finally, I use it with julia +590a63b299. See more here: https://github.com/JuliaLang/juliaup

image

@vtjnash vtjnash closed this as completed Aug 14, 2023
@ufechner7
Copy link
Author

ufechner7 commented Aug 14, 2023

Well, this has not been completed. Please, re-open. There have been two issues mixed up in this issue, one Linux issue and one Windows issue. The original issue is not solved. Out of memory...

@vchuravy vchuravy reopened this Aug 14, 2023
@KristofferC
Copy link
Sponsor Member

I think the solution, for now, is for you to just set JULIA_IMAGE_THREADS=1 to get back the old serial behavior which AFAIU works well to create the sysimage.

@KristofferC KristofferC removed this from the 1.10 milestone Aug 15, 2023
@ufechner7
Copy link
Author

I think the most simple way to resolve this regression is either to use one thread as default, or to use the number of threads passed as -p parameter ...

What do you think?

It is not user friendly to assume that everybody has 32GB of RAM...

@KristofferC
Copy link
Sponsor Member

I think the most simple way to resolve this regression is either to use one thread as the default

That would make it worse in all cases where one does not run out of memory, which is most cases.

or to use the number of threads passed as -p parameter

Not sure what -p (the number of julia processes started for distributed computing) has to do with anything of this

It is not user friendly to assume that everybody has 32GB of RAM...

That is not the assumption. It is not very strange that one has to manually restrict certain resource usage if one builds very large things (like the sysimage in the example here) on relatively less powerful hardware.

@ufechner7
Copy link
Author

ufechner7 commented Aug 16, 2023

Not sure what -p (the number of julia processes started for distributed computing) has to > do with anything of this

Well, my philosophy is better safe than sorry. So by default use one thread, use an existing command line option like -p to specify the number of threads to use or add a new command line option specially for this purpose for the people who want to use more threads...

Alternatively check the free memory before starting a second thread.

I don't think that tuning Julia for speed and accepting that crashes might happen that cannot even be avoided with a command line parameter is a good idea...

As a reminder: In my case my computer stalled completely, I had to press the reset button to continue... Not a nice experience for people who upgrade to Julia 1.10 ...

@ufechner7
Copy link
Author

That would make it worse in all cases where one does not run out of memory, which is most cases.

How do you come to the conclusion that this is "most cases"? I was running out of memory with 16GB RAM, many people have only 4 GB or 8 GB...

@vchuravy
Copy link
Sponsor Member

The number of threads we used is being calculated here:

static unsigned compute_image_thread_count(const ModuleInfo &info) {

From the versioninfo you posted it seems you have 8 threads with 32 GB of RAM.

Could you observe how much memory Julia uses for your case? Does it succeed with JULIA_IMAGE_THREADS=2? How much memory is being used at peak for JULIA_IMAGE_THREADS=1, JULIA_IMAGE_THREADS=2, JULIA_IMAGE_THREADS=4.

I am not sure what would be a satisfactory resolution. We use the same code for both small-ish workloads like pkgimgs and there this heuristic has worked well.
It's also worked well for medium workloads like the Julia system image. Now PackageCompiler.jl creates a very large workload, but it is also the workload that would benefit the most from parallelism.

@ufechner7
Copy link
Author

ufechner7 commented Aug 16, 2023

32 GB of RAM

The versioninfo() I posted is from my private laptop which has 16GB physical RAM.

And as I wrote before:

With 1 thread 1.10 needs 12.7 GB, while 1.9 needs only 10.1GB.
with 2, 4 and 16 threads it always needs 24GB RAM (tested on a different computer)

@vchuravy
Copy link
Sponsor Member

Ah, sorry I misread the numbers then. We could maybe apply a heuristic like total_memory() / 4GB == num_threads?
I am hesitant to do anything that looks at current memory usage since that is very transient.

@ufechner7
Copy link
Author

ufechner7 commented Aug 16, 2023

That would not have helped in my case. Only total_memory() / 16GB = number of threads would have helped, and that is too conservative. So I think if we want to do any dynamic thread allocation we need to look at the free RAM...

@gbaraldi
Copy link
Member

Operating systems usually don't show free ram, if there is ram available they should and do use it for caching stuff. Macos is an example where free memory is very often in the hundred of megabytes but it's data that the OS will store in the disk if another process needs.

@ufechner7
Copy link
Author

ufechner7 commented Aug 16, 2023

MWE for reproducing this issue on Linux (Ubuntu) with 16GB RAM, e.g. a virtual machine with 16GB RAM and 8 cores:

Project.toml:

[deps]
ControlSystems = "a6e380b2-a6ca-5380-bf3e-84a91bcd477e"
DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
ModelingToolkit = "961ee093-0014-501f-94e3-6117800e7a78"
PackageCompiler = "9b87118b-4619-50d2-8e1e-99f35a4d4d9d"

create_sys_image.jl:

using Pkg

@info "Loading packages ..."
using ModelingToolkit, ControlSystems, DataFrames, PackageCompiler

@info "Creating sysimage ..."

PackageCompiler.create_sysimage(
    [:ModelingToolkit, :ControlSystems, :DataFrames];
    sysimage_path="sys-image.so",
    precompile_execution_file="test_for_precompile.jl"
)

test_for_precompile.jl:

using ModelingToolkit, ControlSystems, DataFrames

df = DataFrame([[1, 2], [0, 0]], [:a, :b])

Executing the test:

  • reboot
  • launch terminal
  • execute sudo swapoff -a
  • execute julia --project -e "include(\"create_sys_image.jl\")"

This crashes with the OOM killer on Ubuntu 23.04 and Julia 1.10-beta1. It works fine with Julia 1.9.2.

Just three packages and one line of code...

@ufechner7
Copy link
Author

ufechner7 commented Aug 16, 2023

Macos is an example where free memory is very often in the hundred of megabytes but it's data that the OS will store in the disk if another process needs.

Well, if we implement heuristics we can as well do that OS specific...

@elextr
Copy link

elextr commented Aug 17, 2023

@ufechner7 why do you turn swap off? When there is no swap the OOM killer is likely to be more aggressive since an actual system OOM is much more severe if none can be freed by swapping. If you only do it for the purposes of an MWE thats fine, but in real life having lots of swap might in fact allow you to complete (slowly).

Operating systems usually don't show free ram, if there is ram available they should and do use it for caching stuff.

Also I wonder how much IO cache is used? I would expect generating a sysimage to do quite a bit of IO.

But to my mind the question is why does the memory usage increase significantly with number of threads? Its doing the same total work, making the sysimage, so unless the multithreaded version duplicates many structures(?) I would not have expected multiple threads to use a huge amount more memory. Or is it because multiple threads are generating garbage faster than GC can recycle it, so total memory usage goes up, or is it something else?

If its GC related thats #50658 about the GC needing to be more aggressive when approaching a memory hint.

@ufechner7
Copy link
Author

ufechner7 commented Aug 17, 2023

I turn swap off to have exactly 16GB of RAM to have a reproducible test case...

And yes, I do not really understand why it needs about 24 GB of RAM with two to 16 threads... Two or more does not make a difference, but one needs significantly less RAM...

@elextr
Copy link

elextr commented Aug 17, 2023

It would be good to see the total allocations and GC % for one and two thread cases that complete.

@MariusDrulea
Copy link

MariusDrulea commented Aug 17, 2023

@ufechner7 I run your MWE and the largest RAM usage I have seen is 12.4GB, for that specific julia process. See the picture. I do have a 32GB machine. However, I agree with you that sysimage creation in julia 1.10 shall work by default also on 8GB and 16GB computers.

Screenshot from 2023-08-17 16-20-09

@ufechner7
Copy link
Author

ufechner7 commented Aug 17, 2023

I run your MWE

Which OS are you using? How many cores do you have? I see only three Julia threads, I had 4 threads at 100% CPU usage each when using 1.10.0-beta1 ... I use htop to see RAM usage and CPU usage...

@MariusDrulea
Copy link

I do have 2 laptops, one Windows 10, one Ubuntu 23.04. I do have 4 physical cores on the Ubuntu laptop (8 cores with hyper-threading). At some point I do get 100% usage of all the 4 cores and up to 11 julia threads.

Screenshot from 2023-08-17 21-00-54

@ufechner7
Copy link
Author

ufechner7 commented Aug 17, 2023

I have to admit, this MWE is really at the edge: It works if swap is enabled:
Screenshot from 2023-08-17 20-58-35

With swap disabled it crashes when the memory usage reaches 15.3 GB...

But with Julia 1.9.2 memory usage is not exceeding 9 GB...

@ufechner7
Copy link
Author

Julia 1.10.0-beta2 has a slightly lower memory consumption, so the MWE posted above does not fail any longer... I am working on a new MWE.

@elextr
Copy link

elextr commented Aug 18, 2023

Well if it works and 1.9 works can you please collect the allocation statistics and % GC time for both with single thread vs two threads.

@ufechner7
Copy link
Author

ufechner7 commented Aug 19, 2023

@elextr How can I collect allocation statistics? Do I need to start Julia with a specific parameter?

@ufechner7
Copy link
Author

ufechner7 commented Aug 19, 2023

Julia 1.10. using gcc and g++, not Clang on Ubuntu 22.04, second run

Memory usage as reported by htop:
1.19 GB at the beginning
13.3 GB after 2 min
13.8 GB after 2:20
2:25 finished

julia> @time include("create_sys_image.jl")
[ Info: Loading packages ...
[ Info: Creating sysimage ...
[ Info: PackageCompiler: Executing /home/ufechner/repos/OOM/test_for_precompile.jl => /tmp/jl_packagecompiler_eQv8N5/jl_hWOhev
[ Info: PackageCompiler: Done
✔ [02m:25s] PackageCompiler: compiling incremental system image
159.868005 seconds (11.43 M allocations: 749.595 MiB, 0.27% gc time, 1.54% compilation time: 20% of which was recompilation)

Julia 1.9.2, second run (after restart of Julia)

1.19 GB at the beginning
6.6 GB after 2:00
8.1 GB after 4:30
4:49 min finished

julia> @time include("create_sys_image.jl")
[ Info: Loading packages ...
[ Info: Creating sysimage ...
[ Info: PackageCompiler: Executing /home/ufechner/repos/OOM_1.9.2/test_for_precompile.jl => /tmp/jl_packagecompiler_HiiXlc/jl_grH0hi
[ Info: PackageCompiler: Done
✔ [04m:49s] PackageCompiler: compiling incremental system image
310.205786 seconds (27.75 M allocations: 1.702 GiB, 0.27% gc time, 0.98% compilation time: 24% of which was recompilation)

What you can clearly see is that the reported allocations are pretty misleading. At least with 1.10. I assume that a separate Julia instance is launched and we do not see its allocations...

If we assume that the memory usage at the beginning was by the OS and not by Julia, then Julia 1.9.2 needed 6.9GB RAM (1.7 GB allocations reported) and Julia 1.10-beta2 needed 12.6 GB (0.8GB allocations reported).

With 10GB RAM, e.g. 8GB physical plus 2GB swap this compilation would succeed with 1.9.2 and fail with 1.10.0-beta2.

Perhaps anybody else has an idea where the large difference between reported allocations and memory usage as reported by htop might be coming from?

@ufechner7 ufechner7 changed the title Creating a system image fails in Julia 1.10.0-beta1 while it works with 1.9 Creating a system image fails in Julia 1.10.0-beta2 while it works with 1.9 Aug 19, 2023
@vtjnash
Copy link
Sponsor Member

vtjnash commented Feb 11, 2024

I turn swap off to have exactly 16GB of RAM to have a reproducible test case...

Swap is required, as otherwise it is not possible to use all 16GB of RAM, and a considerable amount of physical memory must be wasted to deal with the overcounting needed for all of the virtual memory that otherwise does not require physical memory due to de-duplication. For compilation machines, we expect the machines to have considerable resources, and we don't expect to reduce that requirement as we know users can access bigger machines if necessary to run the build.

@vtjnash vtjnash closed this as not planned Won't fix, can't repro, duplicate, stale Feb 11, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind:regression Regression in behavior compared to a previous version
Projects
None yet
Development

No branches or pull requests

9 participants