Cách loại bỏ chi phí JIT trong chương trình thực thi của Julia (với MWE)


9

Tôi đang sử dụng PackageCompiler với hy vọng tạo ra một tệp thực thi giúp loại bỏ chi phí biên dịch đúng lúc.

Tài liệu giải thích rằng tôi phải xác định một hàm julia_mainđể gọi logic của chương trình của mình và viết một "tập tin snoop", một tập lệnh gọi các hàm mà tôi muốn biên dịch trước. My julia_mainlấy một đối số duy nhất, vị trí của tệp chứa dữ liệu đầu vào cần phân tích. Vì vậy, để đơn giản, tập tin snoop của tôi chỉ cần thực hiện một cuộc gọi đến julia_mainvới một tập tin đầu vào cụ thể. Vì vậy, tôi hy vọng sẽ thấy tệp thực thi được tạo chạy tốt và nhanh (không có chi phí biên dịch) khi được thực thi đối với cùng tệp đầu vào đó.

Nhưng than ôi, đó không phải là những gì tôi thấy. Trong một ví dụ Julia mới, julia_mainmất khoảng 74 giây cho lần thực hiện đầu tiên và khoảng 4,5 giây cho các lần thực hiện tiếp theo. Tệp thực thi mất khoảng 50 giây mỗi lần nó được gọi.

Việc sử dụng build_executablechức năng của tôi trông như thế này:

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)

Câu hỏi:

  1. Các đối số trên có đúng để đạt được mục tiêu của tôi về một tệp thực thi không có chi phí JIT không?
  2. Có lời khuyên nào khác cho tôi không?

Đây là những gì xảy ra để đáp lại lời kêu gọi đó build_executable. Các dòng từ Start of snoop file execution!để End of snoop file execution!được phát ra bởi mã của tôi.

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> 

BIÊN TẬP

Tôi sợ rằng việc tạo ra một ví dụ làm việc tối thiểu sẽ khó khăn, nhưng nó rất đơn giản:

TestBuildExecutable.jl chứa đựng:

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 chứa đựng:

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

Trong một phiên bản Julia mới, julia_mainmất 8,3 giây cho lần thực hiện đầu tiên và nửa mili giây cho lần thực hiện thứ hai:

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

Vì vậy, tiếp theo tôi gọi 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

Cuối cùng, trong Dấu nhắc lệnh của Windows:

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

D:\temp\builddir15>

mất 8 giây (bằng đồng hồ bấm giờ của tôi) để chạy 8 giây và mất 8 giây để chạy mỗi lần thực hiện, không chỉ lần đầu tiên. Điều này phù hợp với việc thực thi biên dịch JIT mỗi khi nó chạy, nhưng tệp snoop được thiết kế để tránh điều đó!

Thông tin phiên bản:

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"

Câu trả lời:


1

Có vẻ như bạn đang sử dụng Windows.

Tại một số điểm, GóiCompiler.jl sẽ hoàn thiện cho Windows mà bạn có thể dùng thử.


Cảm ơn đã chỉ ra rằng. Tôi đã biết về GóiCompilerX và thật đáng khích lệ khi lưu ý rằng nó đang được phát triển tích cực với bản phát hành ngày hôm nay (11 tháng 12). Tôi sẽ thử nghiệm với nó, nhưng tôi có thể phải kiên nhẫn!
Philip Swannell

1

Giải pháp thực sự là chờ đợi sự tiến bộ PackageCompilerX, như đề xuất của @xiaodai.

Vào ngày 10 tháng 2 năm 2020, thứ trước đây PackageCompilerXđã trở thành một phiên bản mới (phiên bản 1.0) PackageCompiler, với API thay đổi đáng kể và tài liệu kỹ lưỡng hơn.

Cụ thể, MWE ở trên (được thay đổi cho API mới thành PackageCompiler) hiện hoạt động chính xác mà không cần bất kỳ chi phí JIT nào.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.