Description
Description
Pre-compiled code in Julia cannot be used in machines of "similar" architecture. This includes both pre-compiled environments (via Pkg.instantiate()
and system images/apps, both of which are demonstrated in minimal examples.
Related discourse threads [1], [2].
Relevance
This is important for production setups where docker images are built in a CI/CD pipeline (where often times there is limited control on the exact hardware), and then deployed in VMs of specified hardware to serve production.
Minimal, reproducible example
In this examples we demonstrate issues with building a docker image with precompiled Julia code from Intel Cascade Lake
to an AMD EPYC 7B13
. The precompiled code is generated both via Pkg.instantiate()
and via PackageCompiler.jl
, while taking care to specify the correct target cpu_type
.
To reproduce, save the following as Dockerfile
in a c2-standard-4
VM (Intel Cascade Lake
) in google cloud (say, with google's container-optimised OS):
FROM julia:1.9.0
RUN julia -e 'download("https://github.com/JuliaLang/PackageCompiler.jl/archive/refs/tags/v2.1.7.tar.gz", "v2.1.7.tar.gz")'
RUN tar -xf v2.1.7.tar.gz && rm v2.1.7.tar.gz
RUN julia --project=/PackageCompiler.jl-2.1.7/examples/MyApp -e "using Pkg; Pkg.instantiate()"
CMD JULIA_DEBUG=loading julia --project=/PackageCompiler.jl-2.1.7/examples/MyApp -e "using MyApp"
and then build it and pack it by running:
docker build . --tag julia_precompile
docker save julia_precompile > julia_precompile.tar
Then, transfering the resulting docker image into a t2d-standard-4
(AMD EPYC 7B13
) VM in google cloud run:
docker load < julia_precompile.tar
docker run julia_precompile
This shows cache invalidations happening, for example:
┌ Debug: Rejecting cache file /root/.julia/compiled/v1.9/MyApp/6XOLX_U0SK4.ji for MyApp [f943f3d7-887a-4ed5-b0c0-a1d6899aa8f5] since pkgimage can't be loaded on this target
└ @ Base loading.jl:2706
The same issue (incompatibility of targets), appears also when building a system image, even when explicitly specifying the target's CPU (i.e. znver3
for t2d-standard-4
). In this case we get ERROR: Unable to find compatible target in system image
. To reproduce this simply follow the previous steps, but use the following Dockerfile
instead:
FROM julia:1.9.0
RUN julia -e 'download("https://github.com/JuliaLang/PackageCompiler.jl/archive/refs/tags/v2.1.7.tar.gz", "v2.1.7.tar.gz")'
RUN tar -xf v2.1.7.tar.gz && rm v2.1.7.tar.gz
RUN apt-get update && apt-get -f install && apt-get -y install gcc g++ # Required by PackageCompiler
RUN julia -e 'using Pkg; Pkg.develop(path="/PackageCompiler.jl-2.1.7")'
RUN julia --project=/PackageCompiler.jl-2.1.7/examples/MyApp -e 'using PackageCompiler; create_sysimage(["MyApp"]; sysimage_path="/sysimage.so", cpu_target="znver3")'
CMD JULIA_DEBUG=loading julia -J/sysimage.so --project=/PackageCompiler.jl-2.1.7/examples/MyApp -e "using MyApp"
Known, sub-optimal workarounds:
Passing cpu_target="generic"
in PackageCompiler. create_sysimage
avoids the errors/precompilations. However this can result in particularly suboptimal performance.