jolin-io / JuliaScript.jl

finally fast julia scripts
MIT License
79 stars 1 forks source link

Fix juliaup docs #8

Closed PallHaraldsson closed 1 month ago

PallHaraldsson commented 1 month ago

I'll look into more benchmarks, this is from Debian's benchmark game (my old local file), I'll see if others have big gain, and if your script will be accepted there...

A. EDIT: This one could be a false alarm, me measuring randomness, despite attempting lowering load. It at least worked (not much faster, though better after the packagecompile step) 6.75% faster (based on min):

$ killall -SIGSTOP firefox-bin

$ hyperfine 'juliascript pi.jl >/dev/null'
Benchmark 1: juliascript pi.jl >/dev/null
  Time (mean ± σ):      1.902 s ±  0.026 s    [User: 2.270 s, System: 0.526 s]
  Range (min … max):    1.864 s …  1.943 s    10 runs

vs.
$ hyperfine 'julia pi.jl >/dev/null'
Benchmark 1: julia pi.jl >/dev/null
  Time (mean ± σ):      2.069 s ±  0.129 s    [User: 2.369 s, System: 0.565 s]
  Range (min … max):    1.999 s …  2.432 s    10 runs

  Warning: The first benchmarking run for this command was significantly slower than the rest (2.432 s). This could be caused by (filesystem) caches that were not filled until after the first run. You should consider using the '--warmup' option to fill those caches before the actual benchmark. Alternatively, use the '--prepare' option to clear the caches before each timing run.

$ hyperfine 'julia pi.jl >/dev/null'
Benchmark 1: julia pi.jl >/dev/null
  Time (mean ± σ):      2.053 s ±  0.027 s    [User: 2.405 s, System: 0.542 s]
  Range (min … max):    2.013 s …  2.090 s    10 runs

$ hyperfine 'julia pi.jl >/dev/null'
Benchmark 1: julia pi.jl >/dev/null
  Time (mean ± σ):      2.063 s ±  0.032 s    [User: 2.425 s, System: 0.532 s]
  Range (min … max):    2.012 s …  2.120 s    10 runs

$ killall -SIGCONT firefox-bin

machine seemingly still slightly loaded, but previous run before suspending firefox (also that older test was before packagecompile step):

$ hyperfine 'juliascript pi.jl >/dev/null'
Benchmark 1: juliascript pi.jl >/dev/null
  Time (mean ± σ):      2.227 s ±  0.184 s    [User: 2.569 s, System: 0.553 s]
  Range (min … max):    2.048 s …  2.600 s    10 runs

$ hyperfine 'julia pi.jl >/dev/null'
Benchmark 1: julia pi.jl >/dev/null
  Time (mean ± σ):      2.352 s ±  0.243 s    [User: 2.670 s, System: 0.577 s]
  Range (min … max):    2.096 s …  2.844 s    10 runs

$ time juliascript packagecompile pi.jl
  Activating project at `~/.julia/scripts_cache/script_pi_972a5ec309bcd9e922c2a3839c8fe18e9197ea5a1e0bb7a03b6af23bf15a772e`
Precompiling project...
  3 dependencies successfully precompiled in 3 seconds
✔ [01m:44s] PackageCompiler: compiling incremental system image

real    1m54,801s
user    7m33,161s
sys 0m8,613s

$ hyperfine 'juliascript pi.jl >/dev/null'
Benchmark 1: juliascript pi.jl >/dev/null
  Time (mean ± σ):      2.083 s ±  0.148 s    [User: 2.441 s, System: 0.533 s]
  Range (min … max):    1.934 s …  2.341 s    10 runs

B. Didn't work with 1.11, I'm checking if this fixes (likely will):

$ rm ~/.julia/scripts_cache/script_pi_972a5ec309bcd9e922c2a3839c8fe18e9197ea5a1e0bb7a03b6af23bf15a772e/Manifest.toml
pharaldsson@ryksugan:~$ time juliascript packagecompile pi.jl
  Activating project at `~/.julia/scripts_cache/script_pi_972a5ec309bcd9e922c2a3839c8fe18e9197ea5a1e0bb7a03b6af23bf15a772e`
┌ Warning: it is not recommended to create an app/library without a preexisting manifest
└ @ PackageCompiler ~/.julia/packages/PackageCompiler/nT5sD/src/PackageCompiler.jl:75
    Updating registry at `~/.julia/registries/General.toml`
    Updating `~/.julia/scripts_cache/script_pi_972a5ec309bcd9e922c2a3839c8fe18e9197ea5a1e0bb7a03b6af23bf15a772e/Project.toml`
  [aea7be01] + PrecompileTools v1.2.1
    Updating `~/.julia/scripts_cache/script_pi_972a5ec309bcd9e922c2a3839c8fe18e9197ea5a1e0bb7a03b6af23bf15a772e/Manifest.toml`
  [aea7be01] + PrecompileTools v1.2.1
  [21216c6a] + Preferences v1.4.3
  [ade2ca70] + Dates v1.11.0
  [de0858da] + Printf v1.11.0
  [fa267f1f] + TOML v1.0.3
  [4ec0a83e] + Unicode v1.11.0
⢰ [00m:18s] PackageCompiler: compiling incremental system image

older attempt:

$ time juliascript packagecompile pi.jl
Precompiling JuliaScript...
  ✗ REPL
  4 dependencies successfully precompiled in 5 seconds. 26 already precompiled.
  Activating project at `~/.julia/scripts_cache/script_pi_972a5ec309bcd9e922c2a3839c8fe18e9197ea5a1e0bb7a03b6af23bf15a772e`
┌ Warning: The active manifest file has dependencies that were resolved with a different julia version (1.10.5). Unexpected behavior may occur.
└ @ ~/.julia/scripts_cache/script_pi_972a5ec309bcd9e922c2a3839c8fe18e9197ea5a1e0bb7a03b6af23bf15a772e/Manifest.toml:0

I gave up waiting ^C then:

$ time juliascript packagecompile pi.jl
  Activating project at `~/.julia/scripts_cache/script_pi_972a5ec309bcd9e922c2a3839c8fe18e9197ea5a1e0bb7a03b6af23bf15a772e`
┌ Warning: The active manifest file has dependencies that were resolved with a different julia version (1.10.5). Unexpected behavior may occur.
└ @ ~/.julia/scripts_cache/script_pi_972a5ec309bcd9e922c2a3839c8fe18e9197ea5a1e0bb7a03b6af23bf15a772e/Manifest.toml:0
ERROR: InterruptException:
Stacktrace:
 [1] precompile(pkgs::Vector{Pkg.Types.PackageSpec})
   @ Pkg.API ~/.julia/juliaup/julia-1.11.0-rc3+0.x64.linux.gnu/share/julia/stdlib/v1.11/Pkg/src/API.jl:148
 [2] precompile(; name::Nothing, uuid::Nothing, version::Nothing, url::Nothing, rev::Nothing, path::Nothing, mode::Pkg.Types.PackageMode, subdir::Nothing, kwargs::@Kwargs{})
   @ Pkg.API ~/.julia/juliaup/julia-1.11.0-rc3+0.x64.linux.gnu/share/julia/stdlib/v1.11/Pkg/src/API.jl:174
 [3] precompile()
   @ Pkg.API ~/.julia/juliaup/julia-1.11.0-rc3+0.x64.linux.gnu/share/julia/stdlib/v1.11/Pkg/src/API.jl:165
 [4] top-level scope
   @ none:1
schlichtanders commented 1 month ago

Thank you so much for the update to the documentation

PallHaraldsson commented 1 month ago

FYI: Not working in 1.11, still RC3, will see about after release:

$ juliascript pi.jl
fatal: error thrown and no exception handler available.
InitError(mod=:Base, error=AssertionError(msg="isempty(loaded_precompiles)"))
__init__ at ./Base.jl:606
jfptr___init___69822 at /home/pharaldsson/.julia/scripts_cache/script_pi_972a5ec309bcd9e922c2a3839c8fe18e9197ea5a1e0bb7a03b6af23bf15a772e/sysimage.so (unknown line)
jl_apply at /cache/build/tester-amdci5-12/julialang/julia-release-1-dot-11/src/julia.h:2157 [inlined]
jl_module_run_initializer at /cache/build/tester-amdci5-12/julialang/julia-release-1-dot-11/src/toplevel.c:76
_finish_julia_init at /cache/build/tester-amdci5-12/julialang/julia-release-1-dot-11/src/init.c:902
julia_init at /cache/build/tester-amdci5-12/julialang/julia-release-1-dot-11/src/init.c:843
jl_repl_entrypoint at /cache/build/tester-amdci5-12/julialang/julia-release-1-dot-11/src/jlapi.c:1053
main at /cache/build/tester-amdci5-12/julialang/julia-release-1-dot-11/cli/loader_exe.c:58
unknown function (ip: 0x7f6ea93b7d8f)
__libc_start_main at /lib/x86_64-linux-gnu/libc.so.6 (unknown line)
unknown function (ip: 0x4010b8)
schlichtanders commented 1 month ago

thank you for pointing out :pray:

PallHaraldsson commented 1 month ago

I'm not sure why 1.11 worked for a new script (nor why there's slowdown...), though not first time around, and the actual intented script (so sure what other pi script I had):

https://benchmarksgame-team.pages.debian.net/benchmarksgame/program/pidigits-julia-3.html

[Their timing is 1.02 sec, mine is worse... I think they still have an old machine, older than mine?!]

And even more speedup, since shorter runtime, startup overhead larger fraction:

$ hyperfine 'julia pidigits.jl 10000 >/dev/null'
Benchmark 1: julia pidigits.jl 10000 >/dev/null
  Time (mean ± σ):      1.277 s ±  0.034 s    [User: 2.106 s, System: 0.067 s]
  Range (min … max):    1.240 s …  1.354 s    10 runs

$ hyperfine 'juliascript pidigits.jl 10000 >/dev/null'
Benchmark 1: juliascript pidigits.jl 10000 >/dev/null
  Time (mean ± σ):      1.597 s ±  0.039 s    [User: 2.376 s, System: 0.116 s]
  Range (min … max):    1.528 s …  1.658 s    10 runs

and this does not help, since not yet working, at least on 1.11:

$ juliascript packagecompile pidigits.jl 10000
┌ Error: Please run juliascript once normally, so that the precompile statements needed for PackageCompiler are constructed.
└ @ JuliaScript ~/.julia/packages/JuliaScript/KBGYf/src/JuliaScript.jl:21

nor when back to:

$ juliaup default 1.10

$ juliascript packagecompile pidigits.jl 10000
┌ Error: Please run juliascript once normally, so that the precompile statements needed for PackageCompiler are constructed.
└ @ JuliaScript ~/.julia/packages/JuliaScript/KBGYf/src/JuliaScript.jl:21

$ time juliascript pidigits.jl 10000 >/dev/null

real    0m1,680s
user    0m1,933s
sys 0m0,644s
PallHaraldsson commented 1 month ago

Any idea why passing any opt (even "same") is worse?

$ hyperfine 'juliascript pidigits.jl 10000 >/dev/null'
Benchmark 1: juliascript pidigits.jl 10000 >/dev/null
  Time (mean ± σ):      1.594 s ±  0.042 s    [User: 2.362 s, System: 0.127 s]
  Range (min … max):    1.536 s …  1.652 s    10 runs

$ hyperfine 'juliascript -O3 pidigits.jl 10000 >/dev/null'
Benchmark 1: juliascript -O3 pidigits.jl 10000 >/dev/null
  Time (mean ± σ):      3.442 s ±  0.042 s    [User: 4.127 s, System: 0.186 s]
  Range (min … max):    3.361 s …  3.496 s    10 runs

$ hyperfine 'juliascript -O2 pidigits.jl 10000 >/dev/null'
Benchmark 1: juliascript -O2 pidigits.jl 10000 >/dev/null
  Time (mean ± σ):      3.422 s ±  0.021 s    [User: 4.116 s, System: 0.172 s]
  Range (min … max):    3.390 s …  3.458 s    10 runs

hyperfine 'juliascript -O1 pidigits.jl 10000 >/dev/null'
Benchmark 1: juliascript -O1 pidigits.jl 10000 >/dev/null
  Time (mean ± σ):      3.426 s ±  0.055 s    [User: 4.122 s, System: 0.176 s]
  Range (min … max):    3.389 s …  3.569 s    10 runs

and all worse than (all here tested on 1.10 and without packagecompile since it didn't work):

$ hyperfine 'julia -O1 pidigits.jl 10000 >/dev/null'
Benchmark 1: julia -O1 pidigits.jl 10000 >/dev/null
  Time (mean ± σ):      1.253 s ±  0.032 s    [User: 2.087 s, System: 0.062 s]
  Range (min … max):    1.209 s …  1.312 s    10 runs

$ hyperfine 'julia -O3 pidigits.jl 10000 >/dev/null'
Benchmark 1: julia -O3 pidigits.jl 10000 >/dev/null
  Time (mean ± σ):      1.279 s ±  0.019 s    [User: 2.112 s, System: 0.062 s]
  Range (min … max):    1.243 s …  1.301 s    10 runs
schlichtanders commented 1 month ago

The first time it will always track the precompile statements. That takes significant amount of time. But then it should faster. Don't know, but thanks for creating some test examples. Would you mind sharing them?

PallHaraldsson commented 1 month ago

Yes, what do you mean, the full code here? It is above if you click the link.

About:

$ juliascript packagecompile pidigits.jl 10000
┌ Error: Please run juliascript once normally, so that the precompile statements needed for PackageCompiler are constructed.
└ @ JuliaScript ~/.julia/packages/JuliaScript/KBGYf/src/JuliaScript.jl:21

I realize now your package is for scripts with package dependencies, likely why this didn't work. It would be better if it worked robustly either way (I could open an issue), I guess you then have a dilemma knowing if you actually ran first (just output an empty file then?).

It's not going to speed up then, and that's the point, so I'm puzzled why it worked for other the script, pi.jl, also with actual speed-up(?!), since I thought it self-contained.

That one follows:

function calculate_pi(N)
    w = 0

    k = 1
    n1 = BigInt(4)
    n2 = BigInt(3)
    d = BigInt(1)

    i = 0
    while true
        # digit
        u = div(n1, d)
        v = div(n2, d)
        if u == v
            println(u)
            i += 1
            if i % 10 == 0
                println("\t:", i)
            end
            if i == N
                break
            end
            # extract
            u = d * (-10) * u
            n1 = n1 * 10 + u
            n2 = n2 * 10 + u
        else
            # produce
            k2 = k << 1
            u = n1 * (k2 - 1)
            v = n2 + n2
            w = n1 * (k - 1)
            n1 = u + v
            u = n2 * (k + 2)
            n2 = w + u
            d = d * (k2 + 1)
            k += 1
        end
    end

    if i % 10 != 0
        println(" " ^ (10 - i % 10), "\t:", N)
    end
end

# Example usage with N = 50
calculate_pi(10_000)
PallHaraldsson commented 1 month ago

Also FYI:

$ juliascript -O3 pidigits.jl
basename: invalid option -- 'O'
Try 'basename --help' for more information.
sha256sum: invalid option -- 'O'
Try 'sha256sum --help' for more information.
┌ Error: The given file does not exist
└ @ JuliaScript ~/.julia/packages/JuliaScript/KBGYf/src/JuliaScript.jl:47

Why hyperfine took longer. Don't worry about this getting to work, and faster.