AOCL.jl v5.3.1

Hello all,

AOCL is a set of numerical libraries optimized for AMD processors built on the AMD “Zen” architecture, spanning multiple generations. It supports AMD EPYC™, AMD Ryzen™, and AMD Ryzen™ Threadripper™ processor families. These highly tuned, industry-standard math libraries accelerate the development of scientific and high-performance computing applications.

We are happy to announce that AOCL.jl 5.3.1 is now tagged and released.

The AOCL package currently ships the following libraries bundled into a single shared library:

Currently, AOCL BLAS and AOCL LAPACK are made available to use via libblastrampoline. This should allow users to make use of the AOCL BLAS and LAPACK libraries via a simple using AOCL. This package should offer better performance on AMD CPUs, so please try it out.

For questions, feature requests, or issues, please contact toolchainsupport@amd.com

Great to see this.

How does it handle non AMD CPU’s?
Or does it only choose the processing path by the features of the CPU?

AOCL libraries run on any x86 CPU but are optimized to achieve best performance on AMD Zen CPUs (the libraries have dynamic dispatch based on the ISA (instruction set architecture)).

I am very impressed by this.

This can be very useful. Are there some benchmarks? In particular, I am curious how it is compared to OpenBLAS.

Just to clarify, we have made the artifacts of AOCL (AOCL_jll.jl) available only on Linux as of today. Windows support is planned for the future.

Here are some benchmarks I quickly ran. Somewhat mixed results I get:

using LinearAlgebra
using Random
using Printf
using BenchmarkTools

BLAS.set_num_threads(16)

const SIZES = (256, 512, 1024, 2048)

function bench(f, name)
    t = @belapsed $f()
    @printf("%-25s %10.3f ms\n", name, t * 1000)
end


function benchmark_blas_lapack(N, A, B, C, x, y, SPD, SQR)
    println("===== N = $N =====")

    # Level-3 BLAS
    bench("GEMM A * B") do
        mul!(C, A, B)
    end

    # Level-2 BLAS
    bench("GEMV A * x") do
        mul!(y, A, x)
    end

    # LAPACK
    bench("Cholesky") do
        cholesky(SPD)
    end

    bench("LU") do
        lu(SQR)
    end

    bench("QR") do
        qr(SQR)
    end

    bench("Eigen (symmetric)") do
        eigen(Symmetric(SPD))
    end

    println()
end

Random.seed!(1405)
#> TaskLocalRNG()

INPUTS = [
    let
        A = randn(Float64, N, N)
        B = randn(Float64, N, N)
        C = similar(A)

        x = randn(Float64, N)
        y = similar(x)

        # Symmetric positive-definite matrix for Cholesky.
        SPD = A * A' + N * I

        # Separate copy for LU/QR.
        SQR = copy(A)

        (; N, A, B, C, x, y, SPD, SQR)
    end
    for N in SIZES
]

println("BLAS threads: ", BLAS.get_num_threads())
#> BLAS threads: 16
println(BLAS.get_config())
#> LBTConfig([ILP64] libopenblas64_.so)

for inputs in INPUTS
    benchmark_blas_lapack(inputs...)
end
#> ===== N = 256 =====
#> GEMM A * B                     0.117 ms
#> GEMV A * x                     0.004 ms
#> Cholesky                       0.166 ms
#> LU                             0.309 ms
#> QR                             0.887 ms
#> Eigen (symmetric)              5.436 ms
#> 
#> ===== N = 512 =====
#> GEMM A * B                     0.708 ms
#> GEMV A * x                     0.018 ms
#> Cholesky                       1.148 ms
#> LU                             1.424 ms
#> QR                             4.267 ms
#> Eigen (symmetric)             23.321 ms
#> 
#> ===== N = 1024 =====
#> GEMM A * B                     5.049 ms
#> GEMV A * x                     0.027 ms
#> Cholesky                       5.400 ms
#> LU                             5.430 ms
#> QR                            19.333 ms
#> Eigen (symmetric)            103.687 ms
#> 
#> ===== N = 2048 =====
#> GEMM A * B                    40.955 ms
#> GEMV A * x                     0.368 ms
#> Cholesky                      39.240 ms
#> LU                            38.891 ms
#> QR                           134.078 ms
#> Eigen (symmetric)            604.034 ms

using AOCL

println("BLAS threads: ", BLAS.get_num_threads())
#> BLAS threads: 16
println(BLAS.get_config())
#> LBTConfig([ILP64] libaocl64.so, [LP64] libaocl.so)

for inputs in INPUTS
    benchmark_blas_lapack(inputs...)
end
#> ===== N = 256 =====
#> GEMM A * B                     0.079 ms
#> GEMV A * x                     0.004 ms
#> Cholesky                       0.139 ms
#> LU                             0.256 ms
#> QR                             5.201 ms
#> Eigen (symmetric)              6.584 ms
#> 
#> ===== N = 512 =====
#> GEMM A * B                     0.669 ms
#> GEMV A * x                     0.009 ms
#> Cholesky                       1.047 ms
#> LU                             1.080 ms
#> QR                            14.699 ms
#> Eigen (symmetric)             28.969 ms
#> 
#> ===== N = 1024 =====
#> GEMM A * B                     5.218 ms
#> GEMV A * x                     0.022 ms
#> Cholesky                       4.182 ms
#> LU                             4.435 ms
#> QR                            41.410 ms
#> Eigen (symmetric)            110.973 ms
#> 
#> ===== N = 2048 =====
#> GEMM A * B                    45.948 ms
#> GEMV A * x                     0.414 ms
#> Cholesky                      20.869 ms
#> LU                            29.655 ms
#> QR                           169.518 ms
#> Eigen (symmetric)            736.530 ms

Created on 2026-08-11 with MinimalWorkingExamples v1.1.0 using Julia 1.12.6

Environment
Julia Version 1.12.6
Commit 15346901f00 (2026-04-09 19:20 UTC)
Build Info:
  Official https://julialang.org release
Platform Info:
  OS: Linux (x86_64-linux-gnu)
  CPU: 16 × AMD Ryzen 7 8845HS w/ Radeon 780M Graphics
  WORD_SIZE: 64
  LLVM: libLLVM-18.1.7 (ORCJIT, znver3)
  GC: Built with stock GC
Threads: 1 default, 1 interactive, 1 GC (on 16 virtual cores)
Environment:
  JULIA_LOAD_PATH = @:@stdlib

On

"Julia Version 1.12.6"
 "Commit 15346901f00 (2026-04-09 19:20 UTC)"
 "Build Info:"
 "  Official https://julialang.org release"
 "Platform Info:"
 "  OS: Linux (x86_64-linux-gnu)"
 "  CPU: 24 × AMD Ryzen 9 7900X 12-Core Processor"
 "  WORD_SIZE: 64"
 "  LLVM: libLLVM-18.1.7 (ORCJIT, znver4)"
 "  GC: Built with stock GC"
 "Threads: 24 default, 1 interactive, 24 GC (on 24 virtual cores)"
 "Environment:"
 "  JULIA_NUM_THREADS = 24"

using your code, I get

BLAS threads: 24
LBTConfig([ILP64] libopenblas64_.so)
===== N = 256 =====
GEMM A * B                     0.143 ms
GEMV A * x                     0.003 ms
Cholesky                       0.182 ms
LU                             0.270 ms
QR                             0.836 ms
Eigen (symmetric)              5.488 ms

===== N = 512 =====
GEMM A * B                     0.434 ms
GEMV A * x                     0.016 ms
Cholesky                       1.000 ms
LU                             4.142 ms
QR                             4.940 ms
Eigen (symmetric)             33.989 ms

===== N = 1024 =====
GEMM A * B                     2.781 ms
GEMV A * x                     0.028 ms
Cholesky                       4.091 ms
LU                            19.990 ms
QR                            39.375 ms
Eigen (symmetric)            206.905 ms

===== N = 2048 =====
GEMM A * B                    26.754 ms
GEMV A * x                     0.095 ms
Cholesky                      41.085 ms
LU                           119.647 ms
QR                           273.866 ms
Eigen (symmetric)           1328.123 ms

BLAS threads: 24
LBTConfig([ILP64] libaocl64.so, [LP64] libaocl.so)
===== N = 256 =====
GEMM A * B                     0.043 ms
GEMV A * x                     0.003 ms
Cholesky                       0.130 ms
LU                             0.243 ms
QR                             5.412 ms
Eigen (symmetric)              7.036 ms

===== N = 512 =====
GEMM A * B                     0.309 ms
GEMV A * x                     0.013 ms
Cholesky                       0.760 ms
LU                             1.045 ms
QR                            15.458 ms
Eigen (symmetric)            192.932 ms

===== N = 1024 =====
GEMM A * B                     2.400 ms
GEMV A * x                     0.030 ms
Cholesky                       3.028 ms
LU                             4.325 ms
QR                           481.706 ms
Eigen (symmetric)            547.092 ms

===== N = 2048 =====
GEMM A * B                    24.015 ms
GEMV A * x                     0.091 ms
Cholesky                      27.928 ms
LU                            34.289 ms
QR                          2195.568 ms
Eigen (symmetric)           6794.954 ms

As you say, a mixed bag.

This mirrors testing I did with AOCC & BLISS under F95 a few years ago.

YMMV.

D.

The stepped increases in timings, based upon the factors of two, are quite surprising to me. What accounts for that, please? (whether int or float? I assume ints would be significantly speedier. As ints, one would guess that their times, per value,would all be identical). What am I missing here?