Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .githash
Original file line number Diff line number Diff line change
@@ -1 +1 @@
321fb12e0f01f8fb792cb0a49ff877bb6502ad7d
0e886e8fe54067ccc71203f3e23c98fe834c7735
4 changes: 2 additions & 2 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,6 @@ LegatePreferences = "0.1.5"
MacroTools = "0.5.16"
OpenBLAS32_jll = "0.3"
StatsBase = "0.34"
cunumeric_jl_wrapper_jll = "25.10.2"
cupynumeric_jll = "25.10.2"
cunumeric_jl_wrapper_jll = "26.01.00"
cupynumeric_jll = "26.01.00"
julia = "1.10"
158 changes: 72 additions & 86 deletions deps/build.jl
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,9 @@

using Preferences
using Legate
using CNPreferences: CNPreferences
using CNPreferences

const SUPPORTED_CUPYNUMERIC_VERSIONS = ["25.10.00", "25.11.00"]
const LATEST_CUPYNUMERIC_VERSION = SUPPORTED_CUPYNUMERIC_VERSIONS[end]
include("version.jl")

up_dir(dir::String) = abspath(joinpath(dir, ".."))

Expand All @@ -45,7 +44,6 @@ function run_sh(cmd::Cmd, filename::String)

try
run(pipeline(cmd; stdout=tmp_build_log, stderr=err_log, append=false))
println(contents)
contents = read(tmp_build_log, String)
open(build_log, "a") do io
println(contents)
Expand All @@ -61,43 +59,14 @@ function run_sh(cmd::Cmd, filename::String)
end
end

function get_version(version_file)
version = nothing
open(version_file, "r") do f
data = readlines(f)
major = parse(Int, split(data[end - 2])[end])
minor = lpad(split(data[end - 1])[end], 2, '0')
patch = lpad(split(data[end])[end], 2, '0')
version = "$(major).$(minor).$(patch)"
end
if isnothing(version)
error("cuNumeric.jl: Failed to parse version for $(version_file)")
end
return version
end

function get_cupynumeric_version(cupynumeric_root)
version_file = joinpath(cupynumeric_root, "include", "cupynumeric", "version_config.hpp")
return get_version(version_file)
end

function cupynumeric_valid(cupynumeric_root::String)
# todo check if cupynumeric_root matches the version that we are installing.
version_cupynumeric = get_cupynumeric_version(cupynumeric_root)
return version_cupynumeric ∈ SUPPORTED_CUPYNUMERIC_VERSIONS # return true if equal
end

function build_jlcxxwrap(repo_root)
@info "libcxxwrap: Downloading"
function build_jlcxxwrap(repo_root, cupynumeric_root)
build_libcxxwrap = joinpath(repo_root, "scripts/install_cxxwrap.sh")

# this is actually correct even for cunumeric.
version_path = joinpath(DEPOT_PATH[1], "dev/libcxxwrap_julia_jll/override/LEGATE_INSTALL.txt")

if isfile(version_path)
version = strip(read(version_path, String))
if version ∈ SUPPORTED_CUPYNUMERIC_VERSIONS
@info "libcxxwrap: Found supported version built with Legate.jl: $version"
version = VersionNumber(strip(read(version_path, String)))
@info "libcxxwrap: Found cuNumeric $version"
if is_supported_version(version)
@info "libcxxwrap: Found supported version built with cuNumeric.jl: $version"
return nothing
else
@info "libcxxwrap: Unsupported version found: $version. Rebuilding..."
Expand All @@ -109,7 +78,7 @@ function build_jlcxxwrap(repo_root)
@info "libcxxwrap: Running build script: $build_libcxxwrap"
run_sh(`bash $build_libcxxwrap $repo_root`, "libcxxwrap")
open(version_path, "w") do io
write(io, LATEST_CUPYNUMERIC_VERSION)
write(io, string(get_cupynumeric_version(cupynumeric_root)))
end
end

Expand All @@ -118,7 +87,6 @@ function build_cpp_wrapper(
)
@info "libcunumeric_jl_wrapper: Building C++ Wrapper Library"
if isdir(install_root)
@warn "libcunumeric_jl_wrapper: Build dir exists. Deleting prior build."
rm(install_root; recursive=true)
mkdir(install_root)
end
Expand All @@ -142,34 +110,15 @@ function build_cpp_wrapper(
run_sh(`bash $bld_command`, "cpp_wrapper")
end

function replace_nothing_jll(lib, jll)
if isnothing(lib)
eval(:(using $(jll)))
jll_mod = getfield(Main, jll)
lib = joinpath(jll_mod.artifact_dir, "lib")
end
return lib
function _find_jll_artifact_dir(jll)
eval(:(using $(jll)))
jll_mod = getfield(Main, jll)
root = jll_mod.artifact_dir
return root
end

function replace_nothing_conda_jll(mode, lib, jll)
if isnothing(lib)
if mode == CNPreferences.MODE_CONDA
lib = joinpath(load_preference(CNPreferences, "cunumeric_conda_env", nothing), "lib")
else
eval(:(using $(jll)))
jll_mod = getfield(Main, jll)
lib = joinpath(jll_mod.artifact_dir, "lib")
end
end
return lib
end

function build(mode)
if mode == CNPreferences.MODE_JLL
@warn "No reason to Build on JLL mode. Exiting Build"
return nothing
end
pkg_root = abspath(joinpath(@__DIR__, "../"))
function _start_build()
pkg_root = up_dir(@__DIR__)
deps_dir = joinpath(@__DIR__)

build_log = joinpath(deps_dir, "build.log")
Expand All @@ -178,30 +127,67 @@ function build(mode)
end

@info "cuNumeric.jl: Parsed Package Dir as: $(pkg_root)"
return pkg_root
end

"""
build CxxWrap and cunumeric_jl_wrapper
"""
function build_deps(pkg_root, cupynumeric_root, blas_root)
legate_lib = Legate.get_install_liblegate()
cupynumeric_lib = load_preference(CNPreferences, "CUPYNUMERIC_LIB", nothing)
install_lib = joinpath(pkg_root, "lib", "cunumeric_jl_wrapper", "build")
if !cupynumeric_valid(cupynumeric_root)
error(
"cuNumeric.jl: Unsupported cuNumeric version at $(cupynumeric_root). " *
"Installed version: $(installed_version) not in range supported: " *
"$(MIN_CUNUMERIC_VERSION)-$(MAX_CUNUMERIC_VERSION).",
)
end
build_jlcxxwrap(pkg_root, cupynumeric_root)
build_cpp_wrapper(
pkg_root, cupynumeric_root, up_dir(legate_lib), blas_root,
install_lib,
) # $pkg_root/lib/cunumeric_jl_wrapper
end

function build(::CNPreferences.JLL)
@warn "No reason to Build on JLL mode. Exiting Build"
return nothing
end

function build(::CNPreferences.Conda)
@warn "Conda Build does not currently pass our CI. Proceed with caution."
pkg_root = _start_build()

cupynumeric_root = load_preference(CNPreferences, "cunumeric_conda_env", nothing)
if isnothing(cupynumeric_root)
error("This shouldn't happen. cunumeric_conda_env = nothing?")
end

is_cupynumeric_installed(cupynumeric_root; throw_errors=true)
build_deps(pkg_root, cupynumeric_root, cupynumeric_root) # blas is same root as cupynumeric
end

function build(::CNPreferences.Developer)
pkg_root = _start_build()

# can be nothing so this errors if not set
cupynumeric_root = load_preference(CNPreferences, "cunumeric_path", nothing)
blas_lib = load_preference(CNPreferences, "BLAS_LIB", nothing)
if isnothing(cupynumeric_root)
# we are using cupynumeric_jll
cupynumeric_root = _find_jll_artifact_dir(:cupynumeric_jll)
else
# this means we have a custom path set
is_cupynumeric_installed(cupynumeric_root; throw_errors=true)
end

cupynumeric_lib = replace_nothing_conda_jll(mode, cupynumeric_lib, :cupynumeric_jll)
blas_lib = replace_nothing_jll(blas_lib, :OpenBLAS32_jll)

if mode == CNPreferences.MODE_DEVELOPER
install_lib = joinpath(pkg_root, "lib", "cunumeric_jl_wrapper", "build")
build_jlcxxwrap(pkg_root)
cupynumeric_root = up_dir(cupynumeric_lib)
if !cupynumeric_valid(cupynumeric_root)
error(
"cuNumeric.jl: cupynumeric library at $(cupynumeric_root) is not a supported version.
Supported versions are: $(SUPPORTED_CUPYNUMERIC_VERSIONS).",
)
end
build_cpp_wrapper(
pkg_root, cupynumeric_root, up_dir(legate_lib), up_dir(blas_lib),
install_lib,
)
if isnothing(blas_lib)
blas_lib = _find_jll_artifact_dir(:OpenBLAS32_jll)
end

build_deps(pkg_root, cupynumeric_root, up_dir(blas_lib))
end

const mode = load_preference(CNPreferences, "cunumeric_mode", CNPreferences.MODE_JLL)
build(mode)
const mode_str = load_preference(CNPreferences, "cunumeric_mode", CNPreferences.MODE_JLL)
build(CNPreferences.to_mode(mode_str))
64 changes: 64 additions & 0 deletions deps/version.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#= Copyright 2026 Northwestern University,
* Carnegie Mellon University University
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Author(s): David Krasowska <krasow@u.northwestern.edu>
* Ethan Meitz <emeitz@andrew.cmu.edu>
=#

const MIN_CUDA_VERSION = v"13.0"
const MAX_CUDA_VERSION = v"13.9.999"
const MIN_CUNUMERIC_VERSION = v"26.01.00"
const MAX_CUNUMERIC_VERSION = v"26.12.00"

up_dir(dir::String) = abspath(joinpath(dir, ".."))

function get_version(version_file::String)
version = nothing
open(version_file, "r") do f
data = readlines(f)
major = parse(Int, split(data[end - 2])[end])
minor = parse(Int, lpad(split(data[end - 1])[end], 2, '0'))
patch = parse(Int, lpad(split(data[end])[end], 2, '0'))
version = VersionNumber(major, minor, patch)
end
if isnothing(version)
error("cuNumeric.jl: Failed to parse version for $(version_file)")
end
return version
end

function get_cupynumeric_version(cupynumeric_root::String)
version_file = joinpath(cupynumeric_root, "include", "cupynumeric", "version_config.hpp")
return get_version(version_file)
end

function is_supported_version(version::VersionNumber)
return MIN_CUNUMERIC_VERSION <= version && version <= MAX_CUNUMERIC_VERSION
end

function cupynumeric_valid(cupynumeric_root::String)
version_cupynumeric = get_cupynumeric_version(cupynumeric_root)
return is_supported_version(version_cupynumeric)
end

function is_cupynumeric_installed(cupynumeric::String; throw_errors::Bool=false)
include_dir = joinpath(cupynumeric, "include")
if !isdir(joinpath(include_dir, "cupynumeric/cupynumeric"))
throw_errors &&
@error "cuNumeric.jl: Cannot find include/cupynumeric/cupynumeric in $(cupynumeric)"
return false
end
return true
end
27 changes: 1 addition & 26 deletions ext/CUDAExt/cuda.jl
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@

# ndarray_cuda_type(::NDArray{T,2}) where {T} = CuDeviceMatrix{T,1}
# ndarray_cuda_type(::NDArray{T,N}) where {T,N} = CuDeviceArray{T,N,1}

function ndarray_cuda_type(A::NDArray{T,N}) where {T,N}
if N == 1
CuDeviceVector{T,1}
Expand Down Expand Up @@ -78,27 +74,6 @@ function check_sz(arr, maxshape)
end
end

# allignment contrainsts are transitive.
# we can allign all the inputs and then alligns all the outputs
# then allign one input with one output
# This reduces the need for a cartesian product.
function add_default_alignment(
task::Legate.AutoTask, inputs::Vector{Legate.Variable}, outputs::Vector{Legate.Variable}
)
# Align all inputs to the first input
for i in 2:length(inputs)
Legate.add_constraint(task, Legate.align(inputs[i], inputs[1]))
end
# Align all outputs to the first output
for i in 2:length(outputs)
Legate.add_constraint(task, Legate.align(outputs[i], outputs[1]))
end
# Align first output with first input
if !isempty(inputs) && !isempty(outputs)
Legate.add_constraint(task, Legate.align(outputs[1], inputs[1]))
end
end

function Launch(kernel::cuNumeric.CUDATask, inputs::Tuple{Vararg{NDArray}},
outputs::Tuple{Vararg{NDArray}}, scalars::Tuple{Vararg{Any}}; blocks, threads)

Expand Down Expand Up @@ -141,7 +116,7 @@ function Launch(kernel::cuNumeric.CUDATask, inputs::Tuple{Vararg{NDArray}},
end

# all inputs are alligned with all outputs
add_default_alignment(task, input_vars, output_vars)
Legate.add_default_alignment(task, input_vars, output_vars)
Legate.submit_auto_task(rt, task)
end

Expand Down
2 changes: 2 additions & 0 deletions lib/CNPreferences/src/CNPreferences.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ module CNPreferences
using Preferences
using LegatePreferences

const DEVEL_DEFAULT_WRAPPER_BRANCH = "main"

LegatePreferences.@make_preferences("cunumeric_")

end # module CNPreferences
2 changes: 1 addition & 1 deletion lib/cunumeric_jl_wrapper/VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
25.10.2
25.10.3
3 changes: 3 additions & 0 deletions lib/cunumeric_jl_wrapper/include/ndarray_c_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ typedef struct {
typedef struct CN_NDArray CN_NDArray;
typedef struct CN_Type CN_Type;
typedef struct CN_Scalar CN_Scalar;
typedef struct CN_Store CN_Store;

CN_NDArray* nda_store_to_ndarray(CN_Store* st);

uint64_t nda_query_device_memory();

Expand Down
15 changes: 2 additions & 13 deletions lib/cunumeric_jl_wrapper/src/ndarray.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -251,18 +251,7 @@ CN_NDArray* nda_get_slice(CN_NDArray* arr, const CN_Slice* slices,
return new CN_NDArray{NDArray(std::move(result))};
}

CN_NDArray* nda_attach_external(const void* ptr, size_t size, int dim,
const uint64_t* shape, CN_Type type) {
std::vector<uint64_t> shp_vec(shape, shape + dim);
legate::Shape shp = legate::Shape(shp_vec);

legate::ExternalAllocation alloc =
legate::ExternalAllocation::create_sysmem(ptr, size);
legate::mapping::DimOrdering ordering =
legate::mapping::DimOrdering::fortran_order();

auto store = legate::Runtime::get_runtime()->create_store(shp, type.obj,
alloc, ordering);
return new CN_NDArray{cupynumeric::as_array(store)};
CN_NDArray* nda_store_to_ndarray(CN_Store* st) {
return new CN_NDArray{cupynumeric::as_array(st->obj)};
}
} // extern "C"
Loading
Loading