From 5fd4c39881f92709f3a9b62b0dfb7e9824c881ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20S=C3=A1nchez=20Ram=C3=ADrez?= Date: Wed, 8 Jan 2025 02:16:36 +0100 Subject: [PATCH 01/21] linearize kernel args --- ext/ReactantCUDAExt.jl | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/ext/ReactantCUDAExt.jl b/ext/ReactantCUDAExt.jl index 811698210d..0e2ec3a8fb 100644 --- a/ext/ReactantCUDAExt.jl +++ b/ext/ReactantCUDAExt.jl @@ -363,6 +363,11 @@ function to_bytes(x) end end +function Reactant.make_tracer(seen, @nospecialize(prev::CuTracedArray{T,N}), @nospecialize(path), mode; kwargs...) + x = Base.unsafe_pointer_to_objref(Base.reinterpret(Ptr{Cvoid}, prev.ptr))::TracedRArray + return Reactant.make_tracer(seen, x, path, mode; kwargs...) +end + Reactant.@reactant_overlay @noinline function (func::LLVMFunc{F,tt})( args...; convert=Val(false), @@ -385,20 +390,12 @@ Reactant.@reactant_overlay @noinline function (func::LLVMFunc{F,tt})( wrapper_tys = MLIR.IR.Type[] ctx = MLIR.IR.context() cullvm_ty = MLIR.IR.Type(MLIR.API.mlirLLVMArrayTypeGet(MLIR.API.mlirLLVMPointerTypeGet(ctx, 1), 1)) - for (i, a) in Tuple{Int, Any}[(0, func.f), enumerate(args)...] - if sizeof(a) == 0 - continue - end - if a isa CuTracedArray - a = - Base.unsafe_pointer_to_objref(Base.reinterpret(Ptr{Cvoid}, a.ptr))::TracedRArray - end - if a isa TracedRArray || a isa TracedRNumber - push!(wrapper_tys, cullvm_ty) - continue - end - # Per below we assume we can inline all other types directly in - end + + # linearize kernel arguments + seen = Reactant.OrderedIdDict() + prev = Any[func.f, args...] + make_tracer(seen, prev, (:kernelarg,), Reactant.TracedSetPath) + wrapper_tys = fill(cullvm_ty, length(seen)) sym_name = String(gensym("call_$fname")) mod = MLIR.IR.mmodule() From 839050b506e5a85e5c91957b94a8fa325cc66b49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20S=C3=A1nchez=20Ram=C3=ADrez?= <15837247+mofeing@users.noreply.github.com> Date: Wed, 8 Jan 2025 15:35:36 +0100 Subject: [PATCH 02/21] Update ext/ReactantCUDAExt.jl Co-authored-by: jumerckx <31353884+jumerckx@users.noreply.github.com> --- ext/ReactantCUDAExt.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/ReactantCUDAExt.jl b/ext/ReactantCUDAExt.jl index 0e2ec3a8fb..9e273a85af 100644 --- a/ext/ReactantCUDAExt.jl +++ b/ext/ReactantCUDAExt.jl @@ -363,7 +363,7 @@ function to_bytes(x) end end -function Reactant.make_tracer(seen, @nospecialize(prev::CuTracedArray{T,N}), @nospecialize(path), mode; kwargs...) +function Reactant.make_tracer(seen, @nospecialize(prev::CuTracedArray), @nospecialize(path), mode; kwargs...) x = Base.unsafe_pointer_to_objref(Base.reinterpret(Ptr{Cvoid}, prev.ptr))::TracedRArray return Reactant.make_tracer(seen, x, path, mode; kwargs...) end From 5290b0b4f47d72490ad9a893e8b53e9d7e667017 Mon Sep 17 00:00:00 2001 From: "William S. Moses" Date: Wed, 8 Jan 2025 15:56:59 -0500 Subject: [PATCH 03/21] tmp wip --- ext/ReactantCUDAExt.jl | 53 ++++++++++++++++++++++++++++-------------- 1 file changed, 36 insertions(+), 17 deletions(-) diff --git a/ext/ReactantCUDAExt.jl b/ext/ReactantCUDAExt.jl index 9e273a85af..4fe6f294c0 100644 --- a/ext/ReactantCUDAExt.jl +++ b/ext/ReactantCUDAExt.jl @@ -394,7 +394,8 @@ Reactant.@reactant_overlay @noinline function (func::LLVMFunc{F,tt})( # linearize kernel arguments seen = Reactant.OrderedIdDict() prev = Any[func.f, args...] - make_tracer(seen, prev, (:kernelarg,), Reactant.TracedSetPath) + kernelargsym = gensym("kernelarg") + make_tracer(seen, prev, (kernelargsym,), Reactant.TracedSetPath) wrapper_tys = fill(cullvm_ty, length(seen)) sym_name = String(gensym("call_$fname")) @@ -423,10 +424,44 @@ Reactant.@reactant_overlay @noinline function (func::LLVMFunc{F,tt})( gpu_function_type = MLIR.IR.Type(Reactant.TracedUtils.get_attribute_by_name(gpufunc, "function_type")) trueidx = 1 + allocs = MLIR.IR.Value[] for (i, a) in Tuple{Int, Any}[(0, func.f), enumerate(args)...] if sizeof(a) == 0 continue end + + # TODO check for only integer and explicitly non cutraced types + MLIR.IR.block!(wrapbody) do + argty = MLIR.IR.Type(MLIR.API.mlirLLVMFunctionTypeGetInput(gpu_function_type, trueidx-1)) + trueidx += 1 + c1 = MLIR.IR.result(MLIR.Dialects.llvm.mlir_constant(; res=MLIR.IR.Type(Int64), value=MLIR.IR.Attribute(1)), 1) + alloc = MLIR.IR.result(MLIR.Dialects.llvm.alloca(c1; elem_type=MLIR.IR.Attribute(argty), res=MLIR.IR.Type(MLIR.API.mlirLLVMPointerTypeGet(ctx, 0))), 1) + push!(allocs, alloc) + + sz = sizeof(a) + array_ty = MLIR.IR.Type(MLIR.API.mlirLLVMArrayTypeGet(MLIR.IR.Type(Int8), sz)) + cdata = MLIR.IR.result(MLIR.Dialects.llvm.mlir_constant(; res=array_ty, value=MLIR.IR.DenseElementsAttribute(to_bytes(a))), 1) + MLIR.Dialects.llvm.store(cdata, alloc) + argres = MLIR.IR.result(MLIR.Dialects.llvm.load(alloc; res=argty), 1) + push!(wrapargs, argres) + end + + end + + for arg in values(seen) + for p in Reactant.TracedUtils.get_paths(arg) + if p[1] !== kernelargsym + continue + end + # Get the allocation corresponding to which arg we're doing + alloc = allocs[p[2]] + + # we need to now compute the offset in bytes of the path + offset = 0 + ptr = MLIR.gep!(alloc + end + end + if a isa CuTracedArray a = Base.unsafe_pointer_to_objref(Base.reinterpret(Ptr{Cvoid}, a.ptr))::TracedRArray @@ -455,22 +490,6 @@ Reactant.@reactant_overlay @noinline function (func::LLVMFunc{F,tt})( trueidx += 1 continue end - - # TODO check for only integer and explicitly non cutraced types - @show "Warning: using fallback for kernel argument type conversion for argument of type $(Core.Typeof(a)), if this contains a CuTracedArray this will segfault" - MLIR.IR.block!(wrapbody) do - argty = MLIR.IR.Type(MLIR.API.mlirLLVMFunctionTypeGetInput(gpu_function_type, trueidx-1)) - trueidx += 1 - c1 = MLIR.IR.result(MLIR.Dialects.llvm.mlir_constant(; res=MLIR.IR.Type(Int64), value=MLIR.IR.Attribute(1)), 1) - alloc = MLIR.IR.result(MLIR.Dialects.llvm.alloca(c1; elem_type=MLIR.IR.Attribute(argty), res=MLIR.IR.Type(MLIR.API.mlirLLVMPointerTypeGet(ctx, 0))), 1) - - sz = sizeof(a) - array_ty = MLIR.IR.Type(MLIR.API.mlirLLVMArrayTypeGet(MLIR.IR.Type(Int8), sz)) - cdata = MLIR.IR.result(MLIR.Dialects.llvm.mlir_constant(; res=array_ty, value=MLIR.IR.DenseElementsAttribute(to_bytes(a))), 1) - MLIR.Dialects.llvm.store(cdata, alloc) - argres = MLIR.IR.result(MLIR.Dialects.llvm.load(alloc; res=argty), 1) - push!(wrapargs, argres) - end end MLIR.IR.block!(wrapbody) do From 7c401982c4f86e89f1e7e4e5ddec492df3a04a38 Mon Sep 17 00:00:00 2001 From: "William S. Moses" Date: Wed, 8 Jan 2025 15:57:58 -0500 Subject: [PATCH 04/21] fix --- ext/ReactantCUDAExt.jl | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ext/ReactantCUDAExt.jl b/ext/ReactantCUDAExt.jl index 4fe6f294c0..0801f8131d 100644 --- a/ext/ReactantCUDAExt.jl +++ b/ext/ReactantCUDAExt.jl @@ -448,6 +448,7 @@ Reactant.@reactant_overlay @noinline function (func::LLVMFunc{F,tt})( end + argidx = 1 for arg in values(seen) for p in Reactant.TracedUtils.get_paths(arg) if p[1] !== kernelargsym @@ -459,6 +460,10 @@ Reactant.@reactant_overlay @noinline function (func::LLVMFunc{F,tt})( # we need to now compute the offset in bytes of the path offset = 0 ptr = MLIR.gep!(alloc + + store ptr = arg of wrapped index + + argidx += 1 end end From 020fcd3487ea481f98e7c1a682c9b2093c93de9b Mon Sep 17 00:00:00 2001 From: "William S. Moses" Date: Wed, 8 Jan 2025 17:06:08 -0500 Subject: [PATCH 05/21] wip --- deps/ReactantExtra/WORKSPACE | 66 ++++++++++++------------ ext/ReactantCUDAExt.jl | 97 +++++++++++++++++++++++++----------- 2 files changed, 102 insertions(+), 61 deletions(-) diff --git a/deps/ReactantExtra/WORKSPACE b/deps/ReactantExtra/WORKSPACE index 21c094c4a3..7e15bea05e 100644 --- a/deps/ReactantExtra/WORKSPACE +++ b/deps/ReactantExtra/WORKSPACE @@ -95,39 +95,39 @@ LLVM_TARGETS = select({ }) + ["AArch64", "X86", "ARM"] # Uncomment these lines to use a custom LLVM commit -# LLVM_COMMIT = "023dbbaa3eeddd537e2376aa7355e3bcef618908" -# LLVM_SHA256 = "" -# http_archive( -# name = "llvm-raw", -# build_file_content = "# empty", -# sha256 = LLVM_SHA256, -# strip_prefix = "llvm-project-" + LLVM_COMMIT, -# urls = ["https://github.com/llvm/llvm-project/archive/{commit}.tar.gz".format(commit = LLVM_COMMIT)], -# ) -# -# -# load("@bazel_tools//tools/build_defs/repo:utils.bzl", "maybe") -# maybe( -# http_archive, -# name = "llvm_zlib", -# build_file = "@llvm-raw//utils/bazel/third_party_build:zlib-ng.BUILD", -# sha256 = "e36bb346c00472a1f9ff2a0a4643e590a254be6379da7cddd9daeb9a7f296731", -# strip_prefix = "zlib-ng-2.0.7", -# urls = [ -# "https://github.com/zlib-ng/zlib-ng/archive/refs/tags/2.0.7.zip", -# ], -# ) -# -# maybe( -# http_archive, -# name = "llvm_zstd", -# build_file = "@llvm-raw//utils/bazel/third_party_build:zstd.BUILD", -# sha256 = "7c42d56fac126929a6a85dbc73ff1db2411d04f104fae9bdea51305663a83fd0", -# strip_prefix = "zstd-1.5.2", -# urls = [ -# "https://github.com/facebook/zstd/releases/download/v1.5.2/zstd-1.5.2.tar.gz" -# ], -# ) +LLVM_COMMIT = "023dbbaa3eeddd537e2376aa7355e3bcef618908" +LLVM_SHA256 = "" +http_archive( + name = "llvm-raw", + build_file_content = "# empty", + sha256 = LLVM_SHA256, + strip_prefix = "llvm-project-" + LLVM_COMMIT, + urls = ["https://github.com/llvm/llvm-project/archive/{commit}.tar.gz".format(commit = LLVM_COMMIT)], +) + + +load("@bazel_tools//tools/build_defs/repo:utils.bzl", "maybe") +maybe( + http_archive, + name = "llvm_zlib", + build_file = "@llvm-raw//utils/bazel/third_party_build:zlib-ng.BUILD", + sha256 = "e36bb346c00472a1f9ff2a0a4643e590a254be6379da7cddd9daeb9a7f296731", + strip_prefix = "zlib-ng-2.0.7", + urls = [ + "https://github.com/zlib-ng/zlib-ng/archive/refs/tags/2.0.7.zip", + ], +) + +maybe( + http_archive, + name = "llvm_zstd", + build_file = "@llvm-raw//utils/bazel/third_party_build:zstd.BUILD", + sha256 = "7c42d56fac126929a6a85dbc73ff1db2411d04f104fae9bdea51305663a83fd0", + strip_prefix = "zstd-1.5.2", + urls = [ + "https://github.com/facebook/zstd/releases/download/v1.5.2/zstd-1.5.2.tar.gz" + ], +) http_archive( name = "jax", diff --git a/ext/ReactantCUDAExt.jl b/ext/ReactantCUDAExt.jl index 0801f8131d..298d53063d 100644 --- a/ext/ReactantCUDAExt.jl +++ b/ext/ReactantCUDAExt.jl @@ -368,6 +368,27 @@ function Reactant.make_tracer(seen, @nospecialize(prev::CuTracedArray), @nospeci return Reactant.make_tracer(seen, x, path, mode; kwargs...) end +function get_field_offset(T::Type, path) + offset = 0 + current_type = T + + for field in path + # Get the field index + field_idx = findfirst(==(field), fieldnames(current_type)) + if field_idx === nothing + error("Field $field not found in type $current_type") + end + + # Add the offset of this field + offset += fieldoffset(current_type, field_idx) + + # Update current_type to the field's type for next iteration + current_type = fieldtype(current_type, field_idx) + end + + return offset +end + Reactant.@reactant_overlay @noinline function (func::LLVMFunc{F,tt})( args...; convert=Val(false), @@ -395,8 +416,14 @@ Reactant.@reactant_overlay @noinline function (func::LLVMFunc{F,tt})( seen = Reactant.OrderedIdDict() prev = Any[func.f, args...] kernelargsym = gensym("kernelarg") - make_tracer(seen, prev, (kernelargsym,), Reactant.TracedSetPath) - wrapper_tys = fill(cullvm_ty, length(seen)) + Reactant.make_tracer(seen, prev, (kernelargsym,), Reactant.TracedTrack) + wrapper_tys = MLIR.IR.Type[] + for arg in values(seen) + if !(arg isa TracedRArray || arg isa TracedRNumber) + continue + end + push!(wrapper_tys, cullvm_ty) + end sym_name = String(gensym("call_$fname")) mod = MLIR.IR.mmodule() @@ -424,9 +451,14 @@ Reactant.@reactant_overlay @noinline function (func::LLVMFunc{F,tt})( gpu_function_type = MLIR.IR.Type(Reactant.TracedUtils.get_attribute_by_name(gpufunc, "function_type")) trueidx = 1 - allocs = MLIR.IR.Value[] - for (i, a) in Tuple{Int, Any}[(0, func.f), enumerate(args)...] + allocs = Union{MLIR.IR.Value, Nothing}[] + + llvmptr = MLIR.IR.Type(MLIR.API.mlirLLVMPointerTypeGet(ctx, 0)) + i8 = MLIR.IR.Type(UInt8) + allargs = [func.f, args...] + for a in allargs if sizeof(a) == 0 + push!(allocs, nothing) continue end @@ -435,7 +467,7 @@ Reactant.@reactant_overlay @noinline function (func::LLVMFunc{F,tt})( argty = MLIR.IR.Type(MLIR.API.mlirLLVMFunctionTypeGetInput(gpu_function_type, trueidx-1)) trueidx += 1 c1 = MLIR.IR.result(MLIR.Dialects.llvm.mlir_constant(; res=MLIR.IR.Type(Int64), value=MLIR.IR.Attribute(1)), 1) - alloc = MLIR.IR.result(MLIR.Dialects.llvm.alloca(c1; elem_type=MLIR.IR.Attribute(argty), res=MLIR.IR.Type(MLIR.API.mlirLLVMPointerTypeGet(ctx, 0))), 1) + alloc = MLIR.IR.result(MLIR.Dialects.llvm.alloca(c1; elem_type=MLIR.IR.Attribute(argty), res=llvmptr), 1) push!(allocs, alloc) sz = sizeof(a) @@ -450,33 +482,39 @@ Reactant.@reactant_overlay @noinline function (func::LLVMFunc{F,tt})( argidx = 1 for arg in values(seen) + @show arg + if !(arg isa TracedRArray || arg isa TracedRNumber) + continue + end for p in Reactant.TracedUtils.get_paths(arg) if p[1] !== kernelargsym continue end + + arg = arg.mlir_data + arg = Reactant.TracedUtils.transpose_val(arg) + push!(restys, MLIR.IR.type(arg)) + push!(mlir_args, arg) + # Get the allocation corresponding to which arg we're doing - alloc = allocs[p[2]] + alloc = allocs[p[2]]::MLIR.IR.Value # we need to now compute the offset in bytes of the path - offset = 0 - ptr = MLIR.gep!(alloc - - store ptr = arg of wrapped index + julia_arg = allargs[p[2]] + @show p + @show julia_arg + + offset = get_field_offset(typeof(julia_arg), p[3:end]) + @show offset + MLIR.IR.block!(wrapbody) do + c_offset = MLIR.IR.result(MLIR.Dialects.llvm.mlir_constant(; res=MLIR.IR.Type(Int64), value=MLIR.IR.Attribute(1)), 1) + ptr = MLIR.IR.result(MLIR.Dialects.llvm.getelementptr(alloc, [c_offset], res=llvmptr, elem_type=i8, rawConstantIndices=MLIR.IR.Attribute(Int32[typemin(Int32)])), 1) + @show ptr + MLIR.Dialects.llvm.store(MLIR.IR.argument(wrapbody, argidx), ptr) + end argidx += 1 - end - end - if a isa CuTracedArray - a = - Base.unsafe_pointer_to_objref(Base.reinterpret(Ptr{Cvoid}, a.ptr))::TracedRArray - end - if a isa TracedRArray || a isa TracedRNumber - push!(rarrays, a) - arg = a.mlir_data - arg = Reactant.TracedUtils.transpose_val(arg) - push!(restys, MLIR.IR.type(arg)) - push!(mlir_args, arg) push!( aliases, MLIR.IR.Attribute( @@ -490,10 +528,6 @@ Reactant.@reactant_overlay @noinline function (func::LLVMFunc{F,tt})( ), ), ) - push!(wrapargs, MLIR.IR.argument(wrapbody, argidx)) - argidx += 1 - trueidx += 1 - continue end end @@ -521,8 +555,15 @@ Reactant.@reactant_overlay @noinline function (func::LLVMFunc{F,tt})( fn=MLIR.IR.FlatSymbolRefAttribute(sym_name), output_operand_aliases=MLIR.IR.Attribute(output_operand_aliases) ) - for (i, res) in enumerate(rarrays) - res.mlir_data = Reactant.TracedUtils.transpose_val(MLIR.IR.result(call, i)) + + argidx = 1 + for arg in values(seen) + @show arg + if !(arg isa TracedRArray || arg isa TracedRNumber) + continue + end + arg.mlir_data = Reactant.TracedUtils.transpose_val(MLIR.IR.result(call, argidx)) + argidx+=1 end end From 832a20c11ec29065b74d8ed40ec4fee506f80078 Mon Sep 17 00:00:00 2001 From: "William S. Moses" Date: Wed, 8 Jan 2025 18:15:46 -0500 Subject: [PATCH 06/21] fix --- ext/ReactantCUDAExt.jl | 34 +++++++++++++++++----------------- test/integration/cuda.jl | 36 +++++++++++++++++++++++++++++++++--- 2 files changed, 50 insertions(+), 20 deletions(-) diff --git a/ext/ReactantCUDAExt.jl b/ext/ReactantCUDAExt.jl index 298d53063d..d1c31dc5b4 100644 --- a/ext/ReactantCUDAExt.jl +++ b/ext/ReactantCUDAExt.jl @@ -281,6 +281,7 @@ function compile(job) # TODO: on 1.9, this actually creates a context. cache those. entry = GPUCompiler.JuliaContext() do ctx mod, meta = GPUCompiler.compile( + # :llvm, job; optimize=false, cleanup=false, validate=false, libraries=true :llvm, job; optimize=false, cleanup=false, validate=false, libraries=false ) @@ -451,7 +452,7 @@ Reactant.@reactant_overlay @noinline function (func::LLVMFunc{F,tt})( gpu_function_type = MLIR.IR.Type(Reactant.TracedUtils.get_attribute_by_name(gpufunc, "function_type")) trueidx = 1 - allocs = Union{MLIR.IR.Value, Nothing}[] + allocs = Union{Tuple{MLIR.IR.Value, MLIR.IR.Type}, Nothing}[] llvmptr = MLIR.IR.Type(MLIR.API.mlirLLVMPointerTypeGet(ctx, 0)) i8 = MLIR.IR.Type(UInt8) @@ -468,21 +469,18 @@ Reactant.@reactant_overlay @noinline function (func::LLVMFunc{F,tt})( trueidx += 1 c1 = MLIR.IR.result(MLIR.Dialects.llvm.mlir_constant(; res=MLIR.IR.Type(Int64), value=MLIR.IR.Attribute(1)), 1) alloc = MLIR.IR.result(MLIR.Dialects.llvm.alloca(c1; elem_type=MLIR.IR.Attribute(argty), res=llvmptr), 1) - push!(allocs, alloc) - + push!(allocs, (alloc, argty)) + sz = sizeof(a) array_ty = MLIR.IR.Type(MLIR.API.mlirLLVMArrayTypeGet(MLIR.IR.Type(Int8), sz)) cdata = MLIR.IR.result(MLIR.Dialects.llvm.mlir_constant(; res=array_ty, value=MLIR.IR.DenseElementsAttribute(to_bytes(a))), 1) MLIR.Dialects.llvm.store(cdata, alloc) - argres = MLIR.IR.result(MLIR.Dialects.llvm.load(alloc; res=argty), 1) - push!(wrapargs, argres) end end argidx = 1 for arg in values(seen) - @show arg if !(arg isa TracedRArray || arg isa TracedRNumber) continue end @@ -497,24 +495,17 @@ Reactant.@reactant_overlay @noinline function (func::LLVMFunc{F,tt})( push!(mlir_args, arg) # Get the allocation corresponding to which arg we're doing - alloc = allocs[p[2]]::MLIR.IR.Value + alloc = allocs[p[2]][1] # we need to now compute the offset in bytes of the path julia_arg = allargs[p[2]] - @show p - @show julia_arg offset = get_field_offset(typeof(julia_arg), p[3:end]) - @show offset MLIR.IR.block!(wrapbody) do - c_offset = MLIR.IR.result(MLIR.Dialects.llvm.mlir_constant(; res=MLIR.IR.Type(Int64), value=MLIR.IR.Attribute(1)), 1) - ptr = MLIR.IR.result(MLIR.Dialects.llvm.getelementptr(alloc, [c_offset], res=llvmptr, elem_type=i8, rawConstantIndices=MLIR.IR.Attribute(Int32[typemin(Int32)])), 1) - @show ptr + ptr = MLIR.IR.result(MLIR.Dialects.llvm.getelementptr(alloc, MLIR.IR.Value[], res=llvmptr, elem_type=i8, rawConstantIndices=MLIR.IR.Attribute([Int32(offset)])), 1) MLIR.Dialects.llvm.store(MLIR.IR.argument(wrapbody, argidx), ptr) end - argidx += 1 - push!( aliases, MLIR.IR.Attribute( @@ -528,10 +519,20 @@ Reactant.@reactant_overlay @noinline function (func::LLVMFunc{F,tt})( ), ), ) + + argidx += 1 end end MLIR.IR.block!(wrapbody) do + for arg in allocs + if arg === nothing + continue + end + alloc, argty = arg + argres = MLIR.IR.result(MLIR.Dialects.llvm.load(alloc; res=argty), 1) + push!(wrapargs, argres) + end MLIR.Dialects.llvm.call(wrapargs, MLIR.IR.Value[]; callee=MLIR.IR.FlatSymbolRefAttribute(Base.String(fname)), op_bundle_sizes=MLIR.IR.Attribute(Int32[])) MLIR.Dialects.llvm.return_(nothing) end @@ -555,10 +556,9 @@ Reactant.@reactant_overlay @noinline function (func::LLVMFunc{F,tt})( fn=MLIR.IR.FlatSymbolRefAttribute(sym_name), output_operand_aliases=MLIR.IR.Attribute(output_operand_aliases) ) - + argidx = 1 for arg in values(seen) - @show arg if !(arg isa TracedRArray || arg isa TracedRNumber) continue end diff --git a/test/integration/cuda.jl b/test/integration/cuda.jl index 4803a9fe81..598bd9b615 100644 --- a/test/integration/cuda.jl +++ b/test/integration/cuda.jl @@ -72,9 +72,6 @@ function smul!(x) end @static if !Sys.isapple() - -# Broken pending jll update -@static if false @testset "Constant Op Kernel" begin oA = collect(1:1:64) A = Reactant.to_rarray(oA) @@ -87,4 +84,37 @@ end end end + +function tuplef!(tup) + tup[1][] += 2 + return nothing +end + +function tuplef2!(tup) + tup[2][] *= tup[1] + return nothing +end + +tuplef(a) = @cuda threads=1 tuplef!((a,)) +tuplef2(a) = @cuda threads=1 tuplef2!((5, a)) + +@static if !Sys.isapple() +@testset "Structured Kernel Arguments" begin + A = ConcreteRArray(fill(1)) + if CUDA.functional() + @jit tuplef(A) + @test all(Array(A) .≈ 3) + else + @code_hlo optimize = :before_kernel tuplef(A) + end + + A = ConcreteRArray(fill(1)) + if CUDA.functional() + @jit tuplef2(A) + @test all(Array(A) .≈ 5) + else + @code_hlo optimize = :before_kernel tuplef2(A) + end + +end end From a93e4550067e0b2b1ed52b1a758f6c783ceb5002 Mon Sep 17 00:00:00 2001 From: "William S. Moses" Date: Wed, 8 Jan 2025 18:34:32 -0500 Subject: [PATCH 07/21] fixup --- deps/ReactantExtra/API.cpp | 20 ++++++++++++++++---- ext/ReactantCUDAExt.jl | 9 +++++++-- 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/deps/ReactantExtra/API.cpp b/deps/ReactantExtra/API.cpp index 3a54f213aa..f7ada88b22 100644 --- a/deps/ReactantExtra/API.cpp +++ b/deps/ReactantExtra/API.cpp @@ -629,7 +629,8 @@ static mlir::StringAttr renameSymbol(llvm::StringRef oldSymName, static mlir::LogicalResult updateSymbolAndAllUses(mlir::SymbolOpInterface op, mlir::ModuleOp source, mlir::ModuleOp target, - unsigned &lastUsedID) { + unsigned &lastUsedID, + bool &shouldRemove) { using namespace llvm; using namespace mlir; @@ -639,6 +640,13 @@ static mlir::LogicalResult updateSymbolAndAllUses(mlir::SymbolOpInterface op, return success(); } + if (auto func = dyn_cast(op.getOperation())) { + if (func.isExternal()) { + shouldRemove = true; + return success(); + } + } + StringAttr newSymName = renameSymbol(opName, lastUsedID, source, target); if (failed(SymbolTable::replaceAllSymbolUses(op, newSymName, source))) @@ -658,7 +666,7 @@ extern "C" MlirOperation LinkInModule(MlirModule prevModC, MlirModule newModC, unsigned lastUsedID = 0; - for (auto &op : *newMod.getBody()) { + for (auto &op : make_early_inc_range(*newMod.getBody())) { auto symbolOp = dyn_cast(op); if (!symbolOp) continue; @@ -669,10 +677,14 @@ extern "C" MlirOperation LinkInModule(MlirModule prevModC, MlirModule newModC, entryFn = &op; } - if (failed(updateSymbolAndAllUses(symbolOp, newMod, prevMod, lastUsedID))) { + bool shouldRemove = false; + if (failed(updateSymbolAndAllUses(symbolOp, newMod, prevMod, lastUsedID, shouldRemove))) { assert(0 && "failed to update all uses"); } - SymbolTable::setSymbolVisibility(&op, SymbolTable::Visibility::Private); + if (shouldRemove) + op.erase(); + else + SymbolTable::setSymbolVisibility(&op, SymbolTable::Visibility::Private); } prevMod.getBody()->getOperations().splice( prevMod.getBody()->getOperations().end(), diff --git a/ext/ReactantCUDAExt.jl b/ext/ReactantCUDAExt.jl index d1c31dc5b4..6d7570b686 100644 --- a/ext/ReactantCUDAExt.jl +++ b/ext/ReactantCUDAExt.jl @@ -375,9 +375,14 @@ function get_field_offset(T::Type, path) for field in path # Get the field index - field_idx = findfirst(==(field), fieldnames(current_type)) + field_idx = if field isa Integer + field + else + @assert field isa Symbol + findfirst(==(field), fieldnames(current_type)) + end if field_idx === nothing - error("Field $field not found in type $current_type") + error("Field $field not found in type $current_type, fieldnames=$(fieldnames(current_type)) T=$T path=$path") end # Add the offset of this field From fa2a1dfa9ae2ac599762b30d5c0c1efa550d7247 Mon Sep 17 00:00:00 2001 From: "William S. Moses" Date: Wed, 8 Jan 2025 18:48:46 -0500 Subject: [PATCH 08/21] traced type --- ext/ReactantCUDAExt.jl | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ext/ReactantCUDAExt.jl b/ext/ReactantCUDAExt.jl index 6d7570b686..aa2cbb4138 100644 --- a/ext/ReactantCUDAExt.jl +++ b/ext/ReactantCUDAExt.jl @@ -613,6 +613,12 @@ Reactant.@reactant_overlay @noinline function CUDA.cufunction( return Core.Typeof(res)(f, res.entry) end +function Reactant.traced_type( + ::Type{A}, seen::ST, ::Val{mode}, track_numbers +) where {T,N,A<:CuTracedArray,ST,mode} + return A +end + function Reactant.traced_type( ::Type{A}, seen::ST, ::Val{mode}, track_numbers ) where {T,N,A<:CUDA.CuArray{T,N},ST,mode} From 8127ed6d45f0c2a24312a443e49bf4aeb356a284 Mon Sep 17 00:00:00 2001 From: "William S. Moses" Date: Wed, 8 Jan 2025 19:34:29 -0500 Subject: [PATCH 09/21] more fix --- ext/ReactantCUDAExt.jl | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/ext/ReactantCUDAExt.jl b/ext/ReactantCUDAExt.jl index aa2cbb4138..3f55fe574d 100644 --- a/ext/ReactantCUDAExt.jl +++ b/ext/ReactantCUDAExt.jl @@ -366,7 +366,8 @@ end function Reactant.make_tracer(seen, @nospecialize(prev::CuTracedArray), @nospecialize(path), mode; kwargs...) x = Base.unsafe_pointer_to_objref(Base.reinterpret(Ptr{Cvoid}, prev.ptr))::TracedRArray - return Reactant.make_tracer(seen, x, path, mode; kwargs...) + Reactant.make_tracer(seen, x, path, mode; kwargs...) + return prev end function get_field_offset(T::Type, path) @@ -416,7 +417,7 @@ Reactant.@reactant_overlay @noinline function (func::LLVMFunc{F,tt})( wrapper_tys = MLIR.IR.Type[] ctx = MLIR.IR.context() - cullvm_ty = MLIR.IR.Type(MLIR.API.mlirLLVMArrayTypeGet(MLIR.API.mlirLLVMPointerTypeGet(ctx, 1), 1)) + cullvm_ty = MLIR.IR.Type(MLIR.API.mlirLLVMPointerTypeGet(ctx, 1)) # linearize kernel arguments seen = Reactant.OrderedIdDict() @@ -615,7 +616,7 @@ end function Reactant.traced_type( ::Type{A}, seen::ST, ::Val{mode}, track_numbers -) where {T,N,A<:CuTracedArray,ST,mode} +) where {A<:CuTracedArray,ST,mode} return A end From 42496d89bbe986f516f489d74fcb81fe57a4e331 Mon Sep 17 00:00:00 2001 From: "William S. Moses" Date: Wed, 8 Jan 2025 20:40:43 -0500 Subject: [PATCH 10/21] fixup --- ext/ReactantCUDAExt.jl | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/ext/ReactantCUDAExt.jl b/ext/ReactantCUDAExt.jl index 3f55fe574d..fd93560827 100644 --- a/ext/ReactantCUDAExt.jl +++ b/ext/ReactantCUDAExt.jl @@ -282,9 +282,12 @@ function compile(job) entry = GPUCompiler.JuliaContext() do ctx mod, meta = GPUCompiler.compile( # :llvm, job; optimize=false, cleanup=false, validate=false, libraries=true - :llvm, job; optimize=false, cleanup=false, validate=false, libraries=false + :llvm, job; optimize=false, cleanup=false, validate=false, libraries=true + # :llvm, job; optimize=false, cleanup=false, validate=true, libraries=false + # :llvm, job; optimize=false, cleanup=false, validate=false, libraries=false ) + GPUCompiler.link_library!(mod, GPUCompiler.load_runtime(job)) entryname = LLVM.name(meta.entry) GPUCompiler.optimize_module!(job, mod) @@ -320,6 +323,8 @@ function compile(job) end end + GPUCompiler.check_ir(job, mod) + LLVM.strip_debuginfo!(mod) modstr = string(mod) From 7edc8a01c78d9474ab50d6ae193832df4029d914 Mon Sep 17 00:00:00 2001 From: "William S. Moses" Date: Thu, 9 Jan 2025 00:49:31 -0500 Subject: [PATCH 11/21] final diff --- ext/ReactantCUDAExt.jl | 4 ++-- src/utils.jl | 7 ++++++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/ext/ReactantCUDAExt.jl b/ext/ReactantCUDAExt.jl index fd93560827..847d94052d 100644 --- a/ext/ReactantCUDAExt.jl +++ b/ext/ReactantCUDAExt.jl @@ -282,7 +282,7 @@ function compile(job) entry = GPUCompiler.JuliaContext() do ctx mod, meta = GPUCompiler.compile( # :llvm, job; optimize=false, cleanup=false, validate=false, libraries=true - :llvm, job; optimize=false, cleanup=false, validate=false, libraries=true + :llvm, job; optimize=false, cleanup=false, validate=false, libraries=false # :llvm, job; optimize=false, cleanup=false, validate=true, libraries=false # :llvm, job; optimize=false, cleanup=false, validate=false, libraries=false ) @@ -323,7 +323,7 @@ function compile(job) end end - GPUCompiler.check_ir(job, mod) + # GPUCompiler.check_ir(job, mod) LLVM.strip_debuginfo!(mod) modstr = string(mod) diff --git a/src/utils.jl b/src/utils.jl index d1130ed90a..93eccb5b52 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -116,6 +116,9 @@ function should_rewrite_ft(@nospecialize(ft)) if ft.name.name == Symbol("#launch_configuration") return false end + if ft.name.name == Symbol("cudaconvert") + return false + end end end end @@ -161,7 +164,9 @@ function should_rewrite_ft(@nospecialize(ft)) ft <: typeof(Base.getproperty) || ft <: typeof(Base.vect) || ft <: typeof(Base.eltype) || - ft <: typeof(Base.argtail) + ft <: typeof(Base.argtail) || + ft <: typeof(Base.identity) || + ft <: typeof(Adapt.adapt_structure) return false end From f3e1f035d2b6f74645ee74c84350027a5815a975 Mon Sep 17 00:00:00 2001 From: William Moses Date: Thu, 9 Jan 2025 17:28:01 -0500 Subject: [PATCH 12/21] Update WORKSPACE --- deps/ReactantExtra/WORKSPACE | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/deps/ReactantExtra/WORKSPACE b/deps/ReactantExtra/WORKSPACE index 7e15bea05e..ea0c3f2946 100644 --- a/deps/ReactantExtra/WORKSPACE +++ b/deps/ReactantExtra/WORKSPACE @@ -9,7 +9,7 @@ http_archive( urls = ["https://github.com/wsmoses/nsync/archive/{commit}.tar.gz".format(commit = NSYNC_COMMIT)], ) -ENZYMEXLA_COMMIT = "85612ea74731f02aa4e30800038e065912d37ae2" +ENZYMEXLA_COMMIT = "e32977f0539537fdfdb096c3e7a67af630c47203" ENZYMEXLA_SHA256 = "" http_archive( @@ -138,7 +138,9 @@ http_archive( patches = ["@enzyme_ad//:patches/jax.patch"], ) -load("@jax//third_party/xla:workspace.bzl", "XLA_COMMIT", "XLA_SHA256") +# load("@jax//third_party/xla:workspace.bzl", "XLA_COMMIT", "XLA_SHA256") +XLA_COMMIT = "88d46fe4b15fff95eae16c64f612e18b71ff49c5" +XLA_SHA256 = "" http_archive( name = "xla", From 9eacb5efa0ed535c3044c6501f4364a0707f4250 Mon Sep 17 00:00:00 2001 From: "William S. Moses" Date: Thu, 9 Jan 2025 17:29:41 -0500 Subject: [PATCH 13/21] fix --- deps/ReactantExtra/WORKSPACE | 66 ++++++++++++++++++------------------ 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/deps/ReactantExtra/WORKSPACE b/deps/ReactantExtra/WORKSPACE index ea0c3f2946..ba2ef41b23 100644 --- a/deps/ReactantExtra/WORKSPACE +++ b/deps/ReactantExtra/WORKSPACE @@ -95,39 +95,39 @@ LLVM_TARGETS = select({ }) + ["AArch64", "X86", "ARM"] # Uncomment these lines to use a custom LLVM commit -LLVM_COMMIT = "023dbbaa3eeddd537e2376aa7355e3bcef618908" -LLVM_SHA256 = "" -http_archive( - name = "llvm-raw", - build_file_content = "# empty", - sha256 = LLVM_SHA256, - strip_prefix = "llvm-project-" + LLVM_COMMIT, - urls = ["https://github.com/llvm/llvm-project/archive/{commit}.tar.gz".format(commit = LLVM_COMMIT)], -) - - -load("@bazel_tools//tools/build_defs/repo:utils.bzl", "maybe") -maybe( - http_archive, - name = "llvm_zlib", - build_file = "@llvm-raw//utils/bazel/third_party_build:zlib-ng.BUILD", - sha256 = "e36bb346c00472a1f9ff2a0a4643e590a254be6379da7cddd9daeb9a7f296731", - strip_prefix = "zlib-ng-2.0.7", - urls = [ - "https://github.com/zlib-ng/zlib-ng/archive/refs/tags/2.0.7.zip", - ], -) - -maybe( - http_archive, - name = "llvm_zstd", - build_file = "@llvm-raw//utils/bazel/third_party_build:zstd.BUILD", - sha256 = "7c42d56fac126929a6a85dbc73ff1db2411d04f104fae9bdea51305663a83fd0", - strip_prefix = "zstd-1.5.2", - urls = [ - "https://github.com/facebook/zstd/releases/download/v1.5.2/zstd-1.5.2.tar.gz" - ], -) +# LLVM_COMMIT = "023dbbaa3eeddd537e2376aa7355e3bcef618908" +# LLVM_SHA256 = "" +# http_archive( +# name = "llvm-raw", +# build_file_content = "# empty", +# sha256 = LLVM_SHA256, +# strip_prefix = "llvm-project-" + LLVM_COMMIT, +# urls = ["https://github.com/llvm/llvm-project/archive/{commit}.tar.gz".format(commit = LLVM_COMMIT)], +# ) +# +# +# load("@bazel_tools//tools/build_defs/repo:utils.bzl", "maybe") +# maybe( +# http_archive, +# name = "llvm_zlib", +# build_file = "@llvm-raw//utils/bazel/third_party_build:zlib-ng.BUILD", +# sha256 = "e36bb346c00472a1f9ff2a0a4643e590a254be6379da7cddd9daeb9a7f296731", +# strip_prefix = "zlib-ng-2.0.7", +# urls = [ +# "https://github.com/zlib-ng/zlib-ng/archive/refs/tags/2.0.7.zip", +# ], +# ) +# +# maybe( +# http_archive, +# name = "llvm_zstd", +# build_file = "@llvm-raw//utils/bazel/third_party_build:zstd.BUILD", +# sha256 = "7c42d56fac126929a6a85dbc73ff1db2411d04f104fae9bdea51305663a83fd0", +# strip_prefix = "zstd-1.5.2", +# urls = [ +# "https://github.com/facebook/zstd/releases/download/v1.5.2/zstd-1.5.2.tar.gz" +# ], +# ) http_archive( name = "jax", From 9fcf44479c3784e0b253b3001b310ae68b06cfb2 Mon Sep 17 00:00:00 2001 From: "William S. Moses" Date: Thu, 9 Jan 2025 18:06:07 -0500 Subject: [PATCH 14/21] bump enzymexla --- deps/ReactantExtra/WORKSPACE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/ReactantExtra/WORKSPACE b/deps/ReactantExtra/WORKSPACE index ba2ef41b23..2eed90fac1 100644 --- a/deps/ReactantExtra/WORKSPACE +++ b/deps/ReactantExtra/WORKSPACE @@ -9,7 +9,7 @@ http_archive( urls = ["https://github.com/wsmoses/nsync/archive/{commit}.tar.gz".format(commit = NSYNC_COMMIT)], ) -ENZYMEXLA_COMMIT = "e32977f0539537fdfdb096c3e7a67af630c47203" +ENZYMEXLA_COMMIT = "d222454197a52de72a57709505db035db9d1ee62" ENZYMEXLA_SHA256 = "" http_archive( From 97e3f79ec8b6dd0ec30b9ed21438c83e484c5040 Mon Sep 17 00:00:00 2001 From: "William S. Moses" Date: Thu, 9 Jan 2025 18:38:09 -0500 Subject: [PATCH 15/21] bump enzymexla --- deps/ReactantExtra/WORKSPACE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/ReactantExtra/WORKSPACE b/deps/ReactantExtra/WORKSPACE index 2eed90fac1..9e500986b5 100644 --- a/deps/ReactantExtra/WORKSPACE +++ b/deps/ReactantExtra/WORKSPACE @@ -9,7 +9,7 @@ http_archive( urls = ["https://github.com/wsmoses/nsync/archive/{commit}.tar.gz".format(commit = NSYNC_COMMIT)], ) -ENZYMEXLA_COMMIT = "d222454197a52de72a57709505db035db9d1ee62" +ENZYMEXLA_COMMIT = "dce4301cbd61d0670b9ee921f879b73cd5df817f" ENZYMEXLA_SHA256 = "" http_archive( From 6e9a5f227a0c1a1e4c16decf477f70fbd9004e9c Mon Sep 17 00:00:00 2001 From: William Moses Date: Thu, 9 Jan 2025 22:09:25 -0500 Subject: [PATCH 16/21] Update Project.toml --- Project.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Project.toml b/Project.toml index 654e091cb8..58df549bfa 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "Reactant" uuid = "3c362404-f566-11ee-1572-e11a4b42c853" authors = ["William Moses ", "Valentin Churavy ", "Sergio Sánchez Ramírez ", "Paul Berg ", "Avik Pal "] -version = "0.2.17" +version = "0.2.18" [deps] Adapt = "79e6a3ab-5dfb-504d-930d-738a2a938a0e" @@ -67,7 +67,7 @@ PythonCall = "0.9" Random = "1.10" Random123 = "1.7" ReactantCore = "0.1.3" -Reactant_jll = "0.0.37" +Reactant_jll = "0.0.38" Scratch = "1.2" SpecialFunctions = "2" Statistics = "1.10" From 0b2df16a4393e66d302eecaa1ba84965408d5f7b Mon Sep 17 00:00:00 2001 From: William Moses Date: Fri, 10 Jan 2025 00:12:46 -0500 Subject: [PATCH 17/21] Update WORKSPACE --- deps/ReactantExtra/WORKSPACE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/ReactantExtra/WORKSPACE b/deps/ReactantExtra/WORKSPACE index 9e500986b5..37a1dc3fb3 100644 --- a/deps/ReactantExtra/WORKSPACE +++ b/deps/ReactantExtra/WORKSPACE @@ -9,7 +9,7 @@ http_archive( urls = ["https://github.com/wsmoses/nsync/archive/{commit}.tar.gz".format(commit = NSYNC_COMMIT)], ) -ENZYMEXLA_COMMIT = "dce4301cbd61d0670b9ee921f879b73cd5df817f" +ENZYMEXLA_COMMIT = "e89708955e283d7e4250df7f74d1d42fe358f6a8" ENZYMEXLA_SHA256 = "" http_archive( From 1880c7e2dc87f23375352ad1d324c1792b66af3a Mon Sep 17 00:00:00 2001 From: "William S. Moses" Date: Fri, 10 Jan 2025 00:20:40 -0500 Subject: [PATCH 18/21] dont fix printlin --- src/utils.jl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/utils.jl b/src/utils.jl index 93eccb5b52..47a5ea72c6 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -166,6 +166,8 @@ function should_rewrite_ft(@nospecialize(ft)) ft <: typeof(Base.eltype) || ft <: typeof(Base.argtail) || ft <: typeof(Base.identity) || + ft <: typeof(Base.print) || + ft <: typeof(Base.println) || ft <: typeof(Adapt.adapt_structure) return false end From c5a5c141f32ea45b9e51991a9f4db188be6cb6cf Mon Sep 17 00:00:00 2001 From: "William S. Moses" Date: Fri, 10 Jan 2025 00:28:32 -0500 Subject: [PATCH 19/21] libdevice --- src/Compiler.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Compiler.jl b/src/Compiler.jl index 4dacbaa217..3e3cea1348 100644 --- a/src/Compiler.jl +++ b/src/Compiler.jl @@ -293,7 +293,7 @@ function optimization_passes(; no_nan::Bool=false) ) func_passes = join(["canonicalize", "cse", "canonicalize", transform_passes], ",") return join( - ["inline{default-pipeline=canonicalize max-iterations=4}", func_passes], ',' + ["inline{default-pipeline=canonicalize max-iterations=4}", "libdevice-funcs-raise", func_passes], ',' ) end From eef65ce615a95f02b3b3c3c507f4f856161b7208 Mon Sep 17 00:00:00 2001 From: "William S. Moses" Date: Fri, 10 Jan 2025 00:51:00 -0500 Subject: [PATCH 20/21] bump offload commit --- deps/ReactantExtra/WORKSPACE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/ReactantExtra/WORKSPACE b/deps/ReactantExtra/WORKSPACE index 37a1dc3fb3..6bdffaffd9 100644 --- a/deps/ReactantExtra/WORKSPACE +++ b/deps/ReactantExtra/WORKSPACE @@ -9,7 +9,7 @@ http_archive( urls = ["https://github.com/wsmoses/nsync/archive/{commit}.tar.gz".format(commit = NSYNC_COMMIT)], ) -ENZYMEXLA_COMMIT = "e89708955e283d7e4250df7f74d1d42fe358f6a8" +ENZYMEXLA_COMMIT = "4d7c91e5d71fc98b901f7aa40b6deacb449fa873" ENZYMEXLA_SHA256 = "" http_archive( From 1f3a6a6372d5f39239f82a26fef01481f4860711 Mon Sep 17 00:00:00 2001 From: William Moses Date: Fri, 10 Jan 2025 09:11:06 -0500 Subject: [PATCH 21/21] Update Project.toml --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index 58df549bfa..868ea7473b 100644 --- a/Project.toml +++ b/Project.toml @@ -67,7 +67,7 @@ PythonCall = "0.9" Random = "1.10" Random123 = "1.7" ReactantCore = "0.1.3" -Reactant_jll = "0.0.38" +Reactant_jll = "0.0.39" Scratch = "1.2" SpecialFunctions = "2" Statistics = "1.10"