From 559a4981c1c082e63a40f592c8eeabb5dd704b2b Mon Sep 17 00:00:00 2001 From: Adam Beckmeyer Date: Wed, 4 Dec 2024 13:47:36 -0500 Subject: [PATCH 1/2] Remove type-level memoization from Julia fibonacci implementation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Moving numbers to the type-level allows Julia to effectively memoize via its dispatch system and constant propagation. Removing this implicit memoization makes the implementation match the others in the benchmark. As proof, calling "@code_native"" on "fibonacci(Val(10))" gives the results below with the result value of 55 memoized: .text .file "fibonacci" .globl julia_fibonacci_9798 # -- Begin function julia_fibonacci_9798 .p2align 4, 0x90 .type julia_fibonacci_9798,@function julia_fibonacci_9798: # @julia_fibonacci_9798 ; Function Signature: fibonacci(Base.Val{10}) ; ┌ @ In[21]:7 within `fibonacci` \# %bb.0: # %top push rbp mov rbp, rsp mov eax, 55 pop rbp ret .Lfunc_end0: .size julia_fibonacci_9798, .Lfunc_end0-julia_fibonacci_9798 ; └ # -- End function .section ".note.GNU-stack","",@progbits --- fibonacci/julia/code.jl | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/fibonacci/julia/code.jl b/fibonacci/julia/code.jl index 33f00167..6abecbb9 100644 --- a/fibonacci/julia/code.jl +++ b/fibonacci/julia/code.jl @@ -1,15 +1,5 @@ -# base case 1 -fibonacci(::Val{0}) = 0 -# base case 2 -fibonacci(::Val{1}) = 1 -# general case -fibonacci(::Val{n}) where n = fibonacci(Val(n-1)) + fibonacci(Val(n-2)) +fibonacci(n) = n < 2 ? n : fibonacci(n-1) + fibonacci(n-2) -let - u = parse(Int,ARGS[1]) - r = 0 - for i ∈ 1:u - r += fibonacci(Val(i)) - end - println(r) -end \ No newline at end of file +main(u) = println(sum(fibonacci, 1:u)) + +isinteractive() || main(parse(Int, ARGS[1])) From d2c1737fe2c0a647a0d9273ba15c3ecb3fa64b30 Mon Sep 17 00:00:00 2001 From: Adam Beckmeyer Date: Wed, 4 Dec 2024 13:55:59 -0500 Subject: [PATCH 2/2] Optimize julia loop implementation Encapsulating the code in a function allows it to be compiled. The basic compilation unit in Julia is a function, so any code at the top level is not compiled. "@inbounds" macros were removed as they didn't make a difference for performance in this case. All other changes were stylistic to make the code more idiomatic. --- loops/julia/code.jl | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/loops/julia/code.jl b/loops/julia/code.jl index 94277366..8908deff 100644 --- a/loops/julia/code.jl +++ b/loops/julia/code.jl @@ -1,12 +1,13 @@ -let +function main(u) a = zeros(Int,10^4) - u = parse(Int,ARGS[1]) r = rand(1:10^4) - @inbounds for i ∈ 1:10^4 - @inbounds for j ∈ 1:10^5 - a[i] = a[i] + j%u + for i ∈ 1:10^4 + for j ∈ 1:10^5 + a[i] += j%u end - a[i] = a[i] + r + a[i] += r end println(a[r]) -end \ No newline at end of file +end + +isinteractive() || main(parse(Int, first(ARGS)))