R vs Julia vs Python: Number-crunchy MatMul Showdown

1 R vs Julia vs Python(Array shape: 2,048 × 2,048)

1.1 Pre Setups

Julia Number of threds setting: Auto(24 threads)
Code
#Sys.setenv(JULIA_NUM_THREADS =  "auto")
Sys.setenv(JULIA_HOME = "C:/Users/dydgn/AppData/Local/Programs/Julia-1.10.2/bin")

library(JuliaCall)
Warning: package 'JuliaCall' was built under R version 4.2.3
Code
Warning: package 'reticulate' was built under R version 4.2.3
Code
Warning: package 'ggplot2' was built under R version 4.2.3
Warning: package 'tibble' was built under R version 4.2.3
Warning: package 'tidyr' was built under R version 4.2.3
Warning: package 'readr' was built under R version 4.2.3
Warning: package 'purrr' was built under R version 4.2.3
Warning: package 'dplyr' was built under R version 4.2.3
Warning: package 'stringr' was built under R version 4.2.3
Warning: package 'lubridate' was built under R version 4.2.3
── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
✔ dplyr     1.1.4     ✔ readr     2.1.5
✔ forcats   1.0.0     ✔ stringr   1.5.1
✔ ggplot2   3.5.0     ✔ tibble    3.2.1
✔ lubridate 1.9.3     ✔ tidyr     1.3.1
✔ purrr     1.0.2     
── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag()    masks stats::lag()
ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
Code
Warning: package 'tictoc' was built under R version 4.2.3
Code
#JuliaCall::julia_setup()

#julia_command("Threads.nthreads()")
Code
set.seed(927)

n <- 10 #number of execution for performance testing

rdim <- 2^11
cdim <- 2^11


X <- matrix(rexp(rdim*cdim),nrow=rdim)
Y <- matrix(rexp(rdim*cdim),nrow=rdim)

1.2 R

1.2.1 Built-in function(%*%)

Code
tic()

for (i in 1:n) {

  res <- X%*%Y
    
}



toc(quiet = T) -> d_base




dim(res)
[1] 2048 2048
Code
res[1:10,1:4]
          [,1]     [,2]     [,3]     [,4]
 [1,] 2047.106 2032.705 2014.846 2025.337
 [2,] 2079.816 2071.895 2015.727 2095.057
 [3,] 2153.803 2193.711 2101.012 2067.206
 [4,] 2110.557 2055.220 2054.313 2032.720
 [5,] 2103.769 2113.417 2130.301 2038.913
 [6,] 2104.886 2147.855 2182.650 2027.939
 [7,] 1958.304 2106.748 1981.617 2008.407
 [8,] 2067.943 2133.851 2178.068 2122.303
 [9,] 2069.651 2093.392 1980.366 2108.247
[10,] 2088.958 2069.363 1999.237 2066.432

1.2.2 Rfast

Code
Warning: package 'Rfast' was built under R version 4.2.3
Loading required package: Rcpp
Warning: package 'Rcpp' was built under R version 4.2.3
Loading required package: RcppZiggurat
Warning: package 'RcppZiggurat' was built under R version 4.2.3
Loading required package: RcppParallel
Warning: package 'RcppParallel' was built under R version 4.2.3

Attaching package: 'RcppParallel'
The following object is masked from 'package:Rcpp':

    LdFlags

Rfast: 2.1.0
 ___ __ __ __ __    __ __ __ __ __ _             _               __ __ __ __ __     __ __ __ __ __ __   
|  __ __ __ __  |  |  __ __ __ __ _/            / \             |  __ __ __ __ /   /__ __ _   _ __ __\  
| |           | |  | |                         / _ \            | |                        / /          
| |           | |  | |                        / / \ \           | |                       / /          
| |           | |  | |                       / /   \ \          | |                      / /          
| |__ __ __ __| |  | |__ __ __ __           / /     \ \         | |__ __ __ __ _        / /__/\          
|    __ __ __ __|  |  __ __ __ __|         / /__ _ __\ \        |_ __ __ __ _   |      / ___  /           
|   \              | |                    / _ _ _ _ _ _ \                     | |      \/  / /       
| |\ \             | |                   / /           \ \                    | |         / /          
| | \ \            | |                  / /             \ \                   | |        / /          
| |  \ \           | |                 / /               \ \                  | |       / /          
| |   \ \__ __ _   | |                / /                 \ \     _ __ __ __ _| |      / /          
|_|    \__ __ __\  |_|               /_/                   \_\   /_ __ __ __ ___|      \/             team

Attaching package: 'Rfast'
The following object is masked from 'package:tictoc':

    Stack
The following object is masked from 'package:dplyr':

    nth
The following objects are masked from 'package:purrr':

    is_integer, transpose
Code
tic()

for (i in 1:n) {

  res <- mat.mult(X,Y)
    
}



toc(quiet = T) -> d_fast




dim(res)
[1] 2048 2048
Code
res[1:10,1:4]
          [,1]     [,2]     [,3]     [,4]
 [1,] 2047.106 2032.705 2014.846 2025.337
 [2,] 2079.816 2071.895 2015.727 2095.057
 [3,] 2153.803 2193.711 2101.012 2067.206
 [4,] 2110.557 2055.220 2054.313 2032.720
 [5,] 2103.769 2113.417 2130.301 2038.913
 [6,] 2104.886 2147.855 2182.650 2027.939
 [7,] 1958.304 2106.748 1981.617 2008.407
 [8,] 2067.943 2133.851 2178.068 2122.303
 [9,] 2069.651 2093.392 1980.366 2108.247
[10,] 2088.958 2069.363 1999.237 2066.432

1.2.3 Run time

Code
# delta time
R_time <-  c("R(Built-in)" = (d_base$toc[[1]]-d_base$tic[[1]])/n,
             "Rfast(R)" = (d_fast$toc[[1]]-d_fast$tic[[1]])/n)

R_time
R(Built-in)    Rfast(R) 
      4.055       0.731 

1.3 Julia

Code
Julia version 1.10.2 at location C:\Users\dydgn\AppData\Local\Programs\JULIA-~1.2\bin will be used.
Loading setup script for JuliaCall...
Finish loading setup script for JuliaCall.
Code

1.3.1 LinearAlgebra(MKL)

Code
using MKL
Code
using Base.Threads

using LinearAlgebra

num_threds = nthreads()
24
Code

BLAS.get_config()
LinearAlgebra.BLAS.LBTConfig
Libraries: 
├ [ILP64] mkl_rt.2.dll└ [ LP64] mkl_rt.2.dll

1.3.1.1 Just using 1 thread only

Code
BLAS.set_num_threads(1);


res = similar(X);


delta = @elapsed begin;


  for i = 1:n;
  
    
    mul!(res, X, Y)

  # end of for
  end; 


# end of @elapsed
end;




d_1thread = delta/n; println("average time: ",d_1thread)
average time: 0.29672405999999996
Code






res
2048×2048 Matrix{Float64}:
 2047.11  2032.71  2014.85  2025.34  …  1890.79  1999.64  1919.07  1921.74
 2079.82  2071.9   2015.73  2095.06     1984.82  1973.6   2079.82  2033.77
 2153.8   2193.71  2101.01  2067.21     2019.07  2070.65  2093.97  2059.95
 2110.56  2055.22  2054.31  2032.72     1992.02  1955.98  2031.95  1995.92
 2103.77  2113.42  2130.3   2038.91     2084.51  2083.51  2064.74  2029.19
 2104.89  2147.86  2182.65  2027.94  …  2044.18  2012.0   2086.45  1991.17
 1958.3   2106.75  1981.62  2008.41     1899.52  1951.53  2002.62  1987.72
 2067.94  2133.85  2178.07  2122.3      2072.94  2098.65  2252.78  2166.79
 2069.65  2093.39  1980.37  2108.25     2024.45  1955.09  2096.34  2035.18
 2088.96  2069.36  1999.24  2066.43     2001.96  1936.71  2016.09  1991.44
    ⋮                                ⋱              ⋮              
 1990.86  2112.11  2031.98  1973.82     1958.81  1913.79  2020.46  2091.58
 2038.24  2100.25  1994.25  2000.73  …  1994.99  2041.15  2109.07  1962.5
 2183.52  2152.97  2152.88  2076.32     2069.98  2029.54  2143.28  2166.41
 2079.76  2143.39  2072.39  2023.96     2134.88  2035.5   2130.36  2164.87
 1954.84  2043.82  1979.22  1983.66     1972.06  1945.79  2074.24  1927.26
 2025.98  2075.98  2090.81  2105.48     2103.8   2062.18  2103.1   2056.19
 2073.56  2140.23  2136.63  2131.93  …  2042.61  1999.52  2080.21  2020.18
 2081.38  2182.67  2134.26  2169.67     2088.02  2086.62  2169.85  2073.72
 2077.5   2228.69  2036.92  2136.79     2115.07  2053.58  2164.36  2133.05

1.3.1.2 Using All threads(i9-12900k - 24 threads)

Code
BLAS.set_num_threads(num_threds);


res = similar(X);


delta = @elapsed begin;


  for i = 1:n;
  
    
    mul!(res, X, Y)

  # end of for
  end; 


# end of @elapsed
end;




d_Athread = delta/n; println("average time delta: ",d_Athread)
average time delta: 0.038578
Code







res
2048×2048 Matrix{Float64}:
 2047.11  2032.71  2014.85  2025.34  …  1890.79  1999.64  1919.07  1921.74
 2079.82  2071.9   2015.73  2095.06     1984.82  1973.6   2079.82  2033.77
 2153.8   2193.71  2101.01  2067.21     2019.07  2070.65  2093.97  2059.95
 2110.56  2055.22  2054.31  2032.72     1992.02  1955.98  2031.95  1995.92
 2103.77  2113.42  2130.3   2038.91     2084.51  2083.51  2064.74  2029.19
 2104.89  2147.86  2182.65  2027.94  …  2044.18  2012.0   2086.45  1991.17
 1958.3   2106.75  1981.62  2008.41     1899.52  1951.53  2002.62  1987.72
 2067.94  2133.85  2178.07  2122.3      2072.94  2098.65  2252.78  2166.79
 2069.65  2093.39  1980.37  2108.25     2024.45  1955.09  2096.34  2035.18
 2088.96  2069.36  1999.24  2066.43     2001.96  1936.71  2016.09  1991.44
    ⋮                                ⋱              ⋮              
 1990.86  2112.11  2031.98  1973.82     1958.81  1913.79  2020.46  2091.58
 2038.24  2100.25  1994.25  2000.73  …  1994.99  2041.15  2109.07  1962.5
 2183.52  2152.97  2152.88  2076.32     2069.98  2029.54  2143.28  2166.41
 2079.76  2143.39  2072.39  2023.96     2134.88  2035.5   2130.36  2164.87
 1954.84  2043.82  1979.22  1983.66     1972.06  1945.79  2074.24  1927.26
 2025.98  2075.98  2090.81  2105.48     2103.8   2062.18  2103.1   2056.19
 2073.56  2140.23  2136.63  2131.93  …  2042.61  1999.52  2080.21  2020.18
 2081.38  2182.67  2134.26  2169.67     2088.02  2086.62  2169.85  2073.72
 2077.5   2228.69  2036.92  2136.79     2115.07  2053.58  2164.36  2133.05

1.3.2 CUDA.jl

Code
using CUDA
Code

delta = @elapsed begin;
  
  #cudamemcpy(hosttodevice)
  X_d = CuArray(X);
  Y_d = CuArray(Y);
  

  for i = 1:n
    
    
    global res_d = X_d * Y_d;
    #synchronize()
    

  end # end of for


  

# end of @elapsed
end; 




d_gpu = delta/n; println("average time delta: ",d_gpu)
average time delta: 0.00159304
Code



# cudamemcpy(devtohost)
res_gpu = Array(res_d)
2048×2048 Matrix{Float64}:
 2047.11  2032.71  2014.85  2025.34  …  1890.79  1999.64  1919.07  1921.74
 2079.82  2071.9   2015.73  2095.06     1984.82  1973.6   2079.82  2033.77
 2153.8   2193.71  2101.01  2067.21     2019.07  2070.65  2093.97  2059.95
 2110.56  2055.22  2054.31  2032.72     1992.02  1955.98  2031.95  1995.92
 2103.77  2113.42  2130.3   2038.91     2084.51  2083.51  2064.74  2029.19
 2104.89  2147.86  2182.65  2027.94  …  2044.18  2012.0   2086.45  1991.17
 1958.3   2106.75  1981.62  2008.41     1899.52  1951.53  2002.62  1987.72
 2067.94  2133.85  2178.07  2122.3      2072.94  2098.65  2252.78  2166.79
 2069.65  2093.39  1980.37  2108.25     2024.45  1955.09  2096.34  2035.18
 2088.96  2069.36  1999.24  2066.43     2001.96  1936.71  2016.09  1991.44
    ⋮                                ⋱              ⋮              
 1990.86  2112.11  2031.98  1973.82     1958.81  1913.79  2020.46  2091.58
 2038.24  2100.25  1994.25  2000.73  …  1994.99  2041.15  2109.07  1962.5
 2183.52  2152.97  2152.88  2076.32     2069.98  2029.54  2143.28  2166.41
 2079.76  2143.39  2072.39  2023.96     2134.88  2035.5   2130.36  2164.87
 1954.84  2043.82  1979.22  1983.66     1972.06  1945.79  2074.24  1927.26
 2025.98  2075.98  2090.81  2105.48     2103.8   2062.18  2103.1   2056.19
 2073.56  2140.23  2136.63  2131.93  …  2042.61  1999.52  2080.21  2020.18
 2081.38  2182.67  2134.26  2169.67     2088.02  2086.62  2169.85  2073.72
 2077.5   2228.69  2036.92  2136.79     2115.07  2053.58  2164.36  2133.05
Code


# cudafree
X_d = nothing;
Y_d = nothing;
res_d = nothing;
GC.gc(true);


CUDA.memory_status()
Effective GPU memory usage: 18.75% (768.112 MiB/4.000 GiB)
No memory pool is in use.
Code
#CUDA.device_reset!()
Code

println("Is returned CUDA array identical to the CPU product?\t",res==res_gpu)
Is returned CUDA array identical to the CPU product?    false
Code


println("max diff: ",findmax(res - res_gpu))
max diff: (1.2732925824820995e-11, CartesianIndex(306, 724))
Code
println("min diff: ", findmin(res - res_gpu))
min diff: (-1.3642420526593924e-11, CartesianIndex(970, 1850))
Code
println("mean diff: ", mean(res - res_gpu))
mean diff: -5.929501681323224e-16
Code
CUDA.device_reset!()
Code
res_jl <- julia_eval("res_gpu")

identical(res,res_jl)
[1] FALSE
Code
#element mean error
mean(res_jl - res)
[1] -2.233456e-17
Code
zapsmall(res_jl[[1]]) - zapsmall(res[[1]])
[1] 0

1.3.3 Run time

Code
julia_time <- c( "1 thread(LinearAlgebra.jl-MKL)" = julia_eval("d_1thread"),
                 "All 24 threads(LinearAlgebra.jl-MKL)" = julia_eval("d_Athread"),
                 "GPU(CUDA.jl)" = julia_eval("d_gpu"))

1.4 python

Code
import numpy as np
import time
import os
os.environ['KMP_DUPLICATE_LIB_OK']='True'
Code

X = np.copy(r.X)
Y = np.copy(r.Y)

n = int(r.n)
Code
X.shape
(2048, 2048)
Code
Y.shape
(2048, 2048)

1.4.1 NumPy

Code
start = time.perf_counter()


for i in range(n):
    res = np.matmul(X, Y)


end = time.perf_counter()


delta = end - start

print( "%.6f seconds per iteration" % (delta/n) )
0.045324 seconds per iteration
Code
print(res.shape)
(2048, 2048)
Code
res
array([[2047.10565551, 2032.70507574, 2014.84647967, ..., 1999.63884114,
        1919.06919555, 1921.74223736],
       [2079.81604161, 2071.89514933, 2015.72733398, ..., 1973.59569962,
        2079.82349932, 2033.77450943],
       [2153.80302502, 2193.7106802 , 2101.01224193, ..., 2070.64972494,
        2093.96807663, 2059.95003291],
       ...,
       [2073.55690521, 2140.23257199, 2136.63335478, ..., 1999.51994048,
        2080.21192758, 2020.18343522],
       [2081.37574738, 2182.67312663, 2134.25728512, ..., 2086.62128189,
        2169.85038313, 2073.72481224],
       [2077.50015617, 2228.69344825, 2036.92107387, ..., 2053.57839612,
        2164.35596869, 2133.04880866]])
Code
res_py <- py$res

identical(res,res_py)
[1] FALSE
Code
#error
res_py[1:3,1:3] - res[1:3,1:3]
              [,1]          [,2]         [,3]
[1,] -4.092726e-12 -6.821210e-13 0.000000e+00
[2,] -2.728484e-12 -2.728484e-12 2.501110e-12
[3,]  4.547474e-13 -3.637979e-12 2.273737e-12
Code
zapsmall(res_py[[1]]) - zapsmall(res[[1]])
[1] 0

1.4.2 Run time

Code
Python_time <- c("NumPy(Python)" = py$delta/n)

1.5 Run time compairison

Code
bench_time <- c(R_time,julia_time,Python_time)
bench_time
                         R(Built-in)                             Rfast(R) 
                          4.05500000                           0.73100000 
      1 thread(LinearAlgebra.jl-MKL) All 24 threads(LinearAlgebra.jl-MKL) 
                          0.29672406                           0.03857800 
                        GPU(CUDA.jl)                        NumPy(Python) 
                          0.00159304                           0.04532384 
Code
bind_cols(bench_time,names(bench_time)) %>% as_tibble() %>%
  rename( delta = `...1`, Lang = `...2`) %>%
  ggplot(aes(y = Lang, x = delta))+
  scale_x_continuous(name = "Delta time(mean value of 10 trials)") +
  labs(title = "Need for Speed: Array Matmul Benchmark(in Seconds)",
       subtitle = "Array Shape: i = k = j = 2,048")+
  geom_col() +
  #coord_flip()+
  geom_text(
    aes(label = paste0("  ",sprintf("%1.3f",delta),"  "), 
        color = delta > .3, hjust = delta > .3),
    size = 4, fontface = "bold"
  ) + scale_color_manual(values = c("black", "white"), guide = "none") 
New names:
• `` -> `...1`
• `` -> `...2`

Python could relatively be slower than LinearAlgebra due to for loop overheads.

2 Julia(LinearAlgebra.BLAS) vs Python(NumPy) MatMul benchmarks(Array shape: 16,384 × 16,384)

2.1 Pre Setups

Code
set.seed(927)


rdim <- 2^14
cdim <- 2^14


X <- matrix(rexp(rdim*cdim),nrow=rdim)
Y <- matrix(rexp(rdim*cdim),nrow=rdim)

2.2 Julia

Code
Code

BLAS.set_num_threads(num_threds);

res = zeros(size(X));

@time begin

res = mul!(res, X, Y);

end
 16.738047 seconds
16384×16384 Matrix{Float64}:
 16145.4  16237.5  16290.1  16113.8  …  15965.2  16057.3  16216.1  16566.6
 16092.8  16200.3  16217.6  15937.8     15867.6  16144.7  16323.7  16445.3
 16016.6  16400.5  16231.3  16004.4     16129.2  16108.6  16558.1  16563.9
 16048.7  16159.5  16152.8  16219.0     15909.5  15945.4  16006.3  16384.3
 16307.1  16503.8  16565.3  16513.8     16437.1  16562.3  16544.1  16923.6
 16206.5  16420.8  16321.6  16148.1  …  15987.6  16312.0  16467.2  16538.2
 16403.5  16551.5  16624.6  16519.1     16336.6  16809.5  16647.9  16924.9
 16177.3  16406.4  16203.4  16455.3     16206.0  16328.2  16641.1  16447.7
 16223.9  16422.2  16395.2  16636.3     16437.1  16231.1  16867.9  16593.6
 16104.3  16235.7  16293.2  16280.6     16090.3  16220.7  16375.7  16362.7
     ⋮                               ⋱      ⋮                      
 16094.9  16296.0  16383.7  16222.3  …  16436.2  16257.5  16124.8  16501.9
 16098.7  16537.7  16171.9  16330.1     16219.6  16541.4  16417.0  16549.0
 16015.3  16257.7  16440.4  16199.0     16130.9  16192.3  16567.8  16567.4
 16436.9  16248.3  16377.9  16184.5     16014.8  16243.4  16443.5  16715.7
 16183.2  16276.2  16338.9  16114.8     16063.6  16458.9  16336.6  16600.1
 16254.3  16426.3  16651.7  16271.1  …  16331.1  16169.0  16565.2  16686.1
 16461.9  16306.0  16386.5  16432.5     16238.8  16342.9  16551.6  16544.9
 16315.3  16517.2  16525.6  16639.6     16485.2  16413.7  16504.7  16525.7
 15929.0  16222.3  16109.3  16150.4     16272.4  15903.8  16262.0  16344.6
Code

println(size(res))
(16384, 16384)

2.3 Python

Code
import numpy as np
import time
Code

X = np.copy(r.X)
Y = np.copy(r.Y)
Code
X.shape
(16384, 16384)
Code
Y.shape
(16384, 16384)
Code
start = time.time()


res = np.matmul(X, Y)


end = time.time()
delta = end - start

print( "%.6f seconds" % delta )
16.835677 seconds
Code
print(res.shape)
(16384, 16384)
Code
res
array([[16145.35518613, 16237.51261177, 16290.12535126, ...,
        16057.26092885, 16216.13415242, 16566.64089157],
       [16092.8136101 , 16200.33063881, 16217.57796195, ...,
        16144.68736166, 16323.65819236, 16445.33306146],
       [16016.59297562, 16400.5251631 , 16231.25835334, ...,
        16108.64113683, 16558.07956214, 16563.93059869],
       ...,
       [16461.92536761, 16306.03626058, 16386.50745881, ...,
        16342.88313308, 16551.58853449, 16544.93739503],
       [16315.34474901, 16517.23776778, 16525.57650335, ...,
        16413.68844809, 16504.71423128, 16525.66906415],
       [15929.00957041, 16222.32813787, 16109.33658451, ...,
        15903.76378174, 16262.0371546 , 16344.59152634]])

3 Session Info

Code
benchmarkme::get_cpu()
$vendor_id
[1] "GenuineIntel"

$model_name
[1] "12th Gen Intel(R) Core(TM) i9-12900K"

$no_of_cores
[1] 24
Code
benchmarkme::get_ram()
137 GB

3.1 R

Code
R version 4.2.2 (2022-10-31 ucrt)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows 10 x64 (build 22631)

Matrix products: default

locale:
[1] LC_COLLATE=Korean_Korea.utf8  LC_CTYPE=Korean_Korea.utf8   
[3] LC_MONETARY=Korean_Korea.utf8 LC_NUMERIC=C                 
[5] LC_TIME=Korean_Korea.utf8    

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
 [1] Rfast_2.1.0        RcppParallel_5.1.7 RcppZiggurat_0.1.6 Rcpp_1.0.12       
 [5] tictoc_1.2         lubridate_1.9.3    forcats_1.0.0      stringr_1.5.1     
 [9] dplyr_1.1.4        purrr_1.0.2        readr_2.1.5        tidyr_1.3.1       
[13] tibble_3.2.1       ggplot2_3.5.0      tidyverse_2.0.0    reticulate_1.35.0 
[17] JuliaCall_0.17.5  

loaded via a namespace (and not attached):
 [1] here_1.0.1            lattice_0.22-5        png_0.1-8            
 [4] rprojroot_2.0.4       digest_0.6.34         foreach_1.5.2        
 [7] utf8_1.2.4            R6_2.5.1              evaluate_0.23        
[10] httr_1.4.7            pillar_1.9.0          rlang_1.1.3          
[13] rstudioapi_0.15.0     Matrix_1.6-5          rmarkdown_2.25       
[16] labeling_0.4.3        htmlwidgets_1.6.4     munsell_0.5.0        
[19] compiler_4.2.2        xfun_0.42             pkgconfig_2.0.3      
[22] htmltools_0.5.7       tidyselect_1.2.0      codetools_0.2-19     
[25] fansi_1.0.6           tzdb_0.4.0            withr_3.0.0          
[28] rappdirs_0.3.3        grid_4.2.2            jsonlite_1.8.8       
[31] gtable_0.3.4          lifecycle_1.0.4       magrittr_2.0.3       
[34] scales_1.3.0          cli_3.6.2             stringi_1.8.3        
[37] farver_2.1.1          doParallel_1.0.17     benchmarkmeData_1.0.4
[40] generics_0.1.3        vctrs_0.6.5           iterators_1.0.14     
[43] tools_4.2.2           benchmarkme_1.0.8     glue_1.7.0           
[46] hms_1.1.3             parallel_4.2.2        fastmap_1.1.1        
[49] yaml_2.3.8            timechange_0.3.0      colorspace_2.1-0     
[52] knitr_1.45           

3.2 Julia

Code

println(VERSION)
1.10.2
Code
using Pkg
Pkg.status()
Status `C:\Users\dydgn\.julia\environments\v1.10\Project.toml`
  [052768ef] CUDA v5.2.0
  [33e6dc65] MKL v0.6.3
  [6f49c342] RCall v0.14.1
  [fd094767] Suppressor v0.2.6

3.3 Python

Code
import session_info

session_info.show()
-----
numpy               1.24.3
session_info        1.0.0
-----
Python 3.8.18 (default, Sep 11 2023, 13:39:12) [MSC v.1916 64 bit (AMD64)]
Windows-10-10.0.22631-SP0
-----
Session information updated at 2024-03-13 19:16