Julia 실행 파일에서 MIT를 사용하여 JIT 오버 헤드를 제거하는 방법


9

PackageCompiler 를 사용하여 적시에 컴파일 오버 헤드를 제거하는 실행 파일을 만들고 싶습니다 .

이 문서에서는 julia_main프로그램의 논리를 호출 하는 함수 를 정의하고 미리 컴파일하려는 함수를 호출하는 스크립트 인 "스눕 파일"을 작성해야한다고 설명합니다. My julia_main는 분석 할 입력 데이터를 포함하는 파일의 위치 인 단일 인수를 취합니다. 그래서 일을 간단하게 유지하기 위해 내 스눕 파일은 단순히 julia_main특정 입력 파일을 호출 합니다. 따라서 생성 된 실행 파일이 동일한 입력 파일에 대해 실행될 때 컴파일 오버 헤드없이 훌륭하고 빠르게 실행되기를 바랍니다.

그러나 아아, 그것은 내가 보는 것이 아닙니다. 새로운 Julia 인스턴스 julia_main에서는 첫 번째 실행의 경우 약 74 초, 후속 실행의 경우 약 4.5 초가 걸립니다. 실행 파일은 호출 될 때마다 약 50 초가 걸립니다.

build_executable함수 사용은 다음과 같습니다.

julia> using PackageCompiler

julia> build_executable("d:/philip/source/script/julia/jsource/SCRiPTMain.jl",
                        "testexecutable",
                        builddir = "d:/temp/builddir4",
                        snoopfile = "d:/philip/source/script/julia/jsource/snoop.jl",
                        compile = "all",
                        verbose = true)

질문 :

  1. JIT 오버 헤드가없는 실행 파일의 목표를 달성하기 위해 위의 주장이 정확합니까?
  2. 다른 조언이 있습니까?

에 대한 호출에 대한 응답은 다음과 같습니다 build_executable. 에서 선 Start of snoop file execution!으로는 End of snoop file execution!내 코드에 의해 방출된다.

Julia program file:
  "d:\philip\source\script\julia\jsource\SCRiPTMain.jl"
C program file:
  "C:\Users\Philip\.julia\packages\PackageCompiler\CJQcs\examples\program.c"
Build directory:
  "d:\temp\builddir4"
Executing snoopfile: "d:\philip\source\script\julia\jsource\snoop.jl"
Start of snoop file execution!
 Warning: The 'control file' contains the key 'InterpolateCovariance' with value 'true' but that is not supported. Pass a value of 'false' or omit the key altogether.
 @ ValidateInputs d:\Philip\Source\script\Julia\JSource\ValidateInputs.jl:685
Time to build model 20.058000087738037
Saving c:/temp/SCRiPT/SCRiPTModel.jls
Results written to c:/temp/SCRiPT/SCRiPTResultsJulia.json
Time to write file: 3620 milliseconds
Time in method runscript: 76899 milliseconds
End of snoop file execution!
[ Info: used 1313 out of 1320 precompile statements
Build static library "testexecutable.a":
  atexit_hook_copy = copy(Base.atexit_hooks) # make backup
# clean state so that any package we use can carelessly call atexit
empty!(Base.atexit_hooks)
Base.__init__()
Sys.__init__() #fix https://github.com/JuliaLang/julia/issues/30479
using REPL
Base.REPL_MODULE_REF[] = REPL
Mod = @eval module $(gensym("anon_module")) end
# Include into anonymous module to not polute namespace
Mod.include("d:\\\\temp\\\\builddir4\\\\julia_main.jl")
Base._atexit() # run all exit hooks we registered during precompile
empty!(Base.atexit_hooks) # don't serialize the exit hooks we run + added
# atexit_hook_copy should be empty, but who knows what base will do in the future
append!(Base.atexit_hooks, atexit_hook_copy)

Build shared library "testexecutable.dll":
  `'C:\Users\Philip\.julia\packages\WinRPM\Y9QdZ\deps\usr\x86_64-w64-mingw32\sys-root\mingw\bin\gcc.exe' --sysroot 'C:\Users\Philip\.julia\packages\WinRPM\Y9QdZ\deps\usr\x86_64-w64-mingw32\sys-root' -shared '-DJULIAC_PROGRAM_LIBNAME="testexecutable.dll"' -o testexecutable.dll -Wl,--whole-archive testexecutable.a -Wl,--no-whole-archive -std=gnu99 '-IC:\Users\philip\AppData\Local\Julia-1.2.0\include\julia' -DJULIA_ENABLE_THREADING=1 '-LC:\Users\philip\AppData\Local\Julia-1.2.0\bin' -Wl,--stack,8388608 -ljulia -lopenlibm -m64 -Wl,--export-all-symbols`
Build executable "testexecutable.exe":
  `'C:\Users\Philip\.julia\packages\WinRPM\Y9QdZ\deps\usr\x86_64-w64-mingw32\sys-root\mingw\bin\gcc.exe' --sysroot 'C:\Users\Philip\.julia\packages\WinRPM\Y9QdZ\deps\usr\x86_64-w64-mingw32\sys-root' '-DJULIAC_PROGRAM_LIBNAME="testexecutable.dll"' -o testexecutable.exe 'C:\Users\Philip\.julia\packages\PackageCompiler\CJQcs\examples\program.c' testexecutable.dll -std=gnu99 '-IC:\Users\philip\AppData\Local\Julia-1.2.0\include\julia' -DJULIA_ENABLE_THREADING=1 '-LC:\Users\philip\AppData\Local\Julia-1.2.0\bin' -Wl,--stack,8388608 -ljulia -lopenlibm -m64`
Copy Julia libraries to build directory:
  7z.dll
  BugpointPasses.dll
  libamd.2.4.6.dll
  libamd.2.dll
  libamd.dll
  libatomic-1.dll
  libbtf.1.2.6.dll
  libbtf.1.dll
  libbtf.dll
  libcamd.2.4.6.dll
  libcamd.2.dll
  libcamd.dll
  libccalltest.dll
  libccolamd.2.9.6.dll
  libccolamd.2.dll
  libccolamd.dll
  libcholmod.3.0.13.dll
  libcholmod.3.dll
  libcholmod.dll
  libclang.dll
  libcolamd.2.9.6.dll
  libcolamd.2.dll
  libcolamd.dll
  libdSFMT.dll
  libexpat-1.dll
  libgcc_s_seh-1.dll
  libgfortran-4.dll
  libgit2.dll
  libgmp.dll
  libjulia.dll
  libklu.1.3.8.dll
  libklu.1.dll
  libklu.dll
  libldl.2.2.6.dll
  libldl.2.dll
  libldl.dll
  libllvmcalltest.dll
  libmbedcrypto.dll
  libmbedtls.dll
  libmbedx509.dll
  libmpfr.dll
  libopenblas64_.dll
  libopenlibm.dll
  libpcre2-8-0.dll
  libpcre2-8.dll
  libpcre2-posix-2.dll
  libquadmath-0.dll
  librbio.2.2.6.dll
  librbio.2.dll
  librbio.dll
  libspqr.2.0.9.dll
  libspqr.2.dll
  libspqr.dll
  libssh2.dll
  libssp-0.dll
  libstdc++-6.dll
  libsuitesparseconfig.5.4.0.dll
  libsuitesparseconfig.5.dll
  libsuitesparseconfig.dll
  libsuitesparse_wrapper.dll
  libumfpack.5.7.8.dll
  libumfpack.5.dll
  libumfpack.dll
  libuv-2.dll
  libwinpthread-1.dll
  LLVM.dll
  LLVMHello.dll
  zlib1.dll
All done

julia> 

편집하다

최소한의 실례를 만드는 것이 어려울 것이지만 두려워했습니다.

TestBuildExecutable.jl 포함한다 :

module TestBuildExecutable

Base.@ccallable function julia_main(ARGS::Vector{String}=[""])::Cint
    @show sum(myarray())
    return 0
end

#Function which takes approx 8 seconds to compile. Returns a 500 x 20 array of 1s
function myarray()
    [1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1;
     1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1;

# PLEASE EDIT TO INSERT THE MISSING 496 LINES, EACH IDENTICAL TO THE LINE ABOVE!

     1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1;
     1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1]
end

end #module

SnoopFile.jl 포함한다 :

module SnoopFile

currentpath = dirname(@__FILE__)
push!(LOAD_PATH, currentpath)
unique!(LOAD_PATH)

using TestBuildExecutable

println("Start of snoop file execution!")
TestBuildExecutable.julia_main()
println("End of snoop file execution!")

end # module

새로운 Julia 인스턴스에서는 julia_main첫 번째 실행에 8.3 초, 두 번째 실행에 0.5 밀리 초가 걸립니다.

julia> @time TestBuildExecutable.julia_main()
sum(myarray()) = 10000
  8.355108 seconds (425.36 k allocations: 25.831 MiB, 0.06% gc time)
0

julia> @time TestBuildExecutable.julia_main()
sum(myarray()) = 10000
  0.000537 seconds (25 allocations: 82.906 KiB)
0

그래서 다음에 전화합니다 build_executable.

julia> using PackageCompiler

julia> build_executable("d:/philip/source/script/julia/jsource/TestBuildExecutable.jl",
                       "testexecutable",
                       builddir = "d:/temp/builddir15",
                       snoopfile = "d:/philip/source/script/julia/jsource/SnoopFile.jl",
                       verbose = false)
Julia program file:
  "d:\philip\source\script\julia\jsource\TestBuildExecutable.jl"
C program file:
  "C:\Users\Philip\.julia\packages\PackageCompiler\CJQcs\examples\program.c"
Build directory:
  "d:\temp\builddir15"
Start of snoop file execution!
sum(myarray()) = 10000
End of snoop file execution!
[ Info: used 79 out of 79 precompile statements
All done

마지막으로 Windows 명령 프롬프트에서 :

D:\temp\builddir15>testexecutable
sum(myarray()) = 1000

D:\temp\builddir15>

스톱워치가 실행하는 데 8 초가 걸렸으며 처음 실행될 때가 아니라 실행될 때마다 8 초가 걸렸습니다. 이것은 실행될 때마다 JIT 컴파일을 수행하는 실행 파일과 일치하지만 snoop 파일은이를 피하도록 설계되었습니다!

버전 정보 :

julia> versioninfo()
Julia Version 1.2.0
Commit c6da87ff4b (2019-08-20 00:03 UTC)
Platform Info:
  OS: Windows (x86_64-w64-mingw32)
  CPU: Intel(R) Core(TM) i7-6700 CPU @ 3.40GHz
  WORD_SIZE: 64
  LIBM: libopenlibm
  LLVM: libLLVM-6.0.1 (ORCJIT, skylake)
Environment:
  JULIA_NUM_THREADS = 8
  JULIA_EDITOR = "C:\Users\Philip\AppData\Local\Programs\Microsoft VS Code\Code.exe"

답변:


1

Windows를 사용중인 것 같습니다.

언젠가 PackageCompiler.jl 은 (는) 시도해볼 수있는 Windows 용 소프트웨어입니다.


지적 해 주셔서 감사합니다. PackageCompilerX에 대해 알고 있었으며 오늘 릴리스 (12 월 11 일)와 함께 현재 개발 중이라는 점에 주목하고 있습니다. 실험 해 보 겠지만 인내심을 가져야 할 수도 있습니다!
Philip Swannell '12

1

해결책은 PackageCompilerX@xiaodai가 제안한대로 진행을 기다리는 것입니다 .

2020 년 2 월 10 일 , API가 크게 변경되고보다 철저한 문서 PackageCompilerX가 제공되면서 이전 의 새로운 버전 (버전 1.0)이 PackageCompiler되었습니다.

특히, (위의 MWE 돌연변이 에 새로운 API에 대한이 PackageCompiler) 이제 어떤 JIT 오버 헤드없이 올바르게 작동합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.