v4.5 tag update (#3202)
* Python DSL examples reorganization. * v4.5 tag update.
This commit is contained in:
107
examples/python/CuTeDSL/dsl_tutorials/export/export_to_c.py
Normal file
107
examples/python/CuTeDSL/dsl_tutorials/export/export_to_c.py
Normal file
@@ -0,0 +1,107 @@
|
||||
# Copyright (c) 2025 - 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
|
||||
# 1. Redistributions of source code must retain the above copyright notice, this
|
||||
# list of conditions and the following disclaimer.
|
||||
|
||||
# 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
|
||||
# 3. Neither the name of the copyright holder nor the names of its
|
||||
# contributors may be used to endorse or promote products derived from
|
||||
# this software without specific prior written permission.
|
||||
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
import cutlass
|
||||
import cutlass.cute as cute
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
import cuda.bindings.driver as cuda
|
||||
|
||||
"""Example demonstrating how to export a CuTe function.
|
||||
|
||||
This example shows how to:
|
||||
1. Compile a CuTe function
|
||||
2. Export the compiled function to a object file and a C header file
|
||||
3. Compile the object file to a shared library
|
||||
|
||||
To run this example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
# export the compiled function to a object file and a C header file
|
||||
python cutlass_ir/compiler/python/examples/cute/export/export_to_c.py
|
||||
"""
|
||||
|
||||
|
||||
@cute.kernel
|
||||
def print_tensor_kernel(a: cute.Tensor):
|
||||
cute.printf("a: {}", a)
|
||||
|
||||
|
||||
@cute.jit
|
||||
def print_tensor(a: cute.Tensor, stream: cuda.CUstream):
|
||||
print_tensor_kernel(a).launch(grid=(1, 1, 1), block=(1, 1, 1), stream=stream)
|
||||
|
||||
|
||||
@cute.kernel
|
||||
def add_one_kernel(a: cute.Tensor, b: cute.Tensor):
|
||||
a[0] = b[0] + 1
|
||||
|
||||
|
||||
@cute.jit
|
||||
def add_one(a: cute.Tensor, b: cute.Tensor, stream: cuda.CUstream):
|
||||
add_one_kernel(a, b).launch(grid=(1, 1, 1), block=(1, 1, 1), stream=stream)
|
||||
|
||||
|
||||
def run():
|
||||
from cutlass.cute.runtime import make_fake_compact_tensor
|
||||
|
||||
shape = (cute.SymInt(divisibility=16), cute.SymInt())
|
||||
a = make_fake_compact_tensor(cutlass.Float32, shape, stride_order=(1, 0))
|
||||
b = make_fake_compact_tensor(cutlass.Float32, shape, stride_order=(1, 0))
|
||||
stream = cuda.CUstream(0)
|
||||
compiled_print_tensor = cute.compile(print_tensor, a, stream=stream)
|
||||
compiled_add_one = cute.compile(add_one, a, b, stream=stream)
|
||||
|
||||
os.makedirs("./build", exist_ok=True)
|
||||
compiled_print_tensor.export_to_c(
|
||||
file_path="./build",
|
||||
file_name="print_tensor_example",
|
||||
function_prefix="print_tensor",
|
||||
)
|
||||
compiled_add_one.export_to_c(
|
||||
file_path="./build", file_name="add_one_example", function_prefix="add_one"
|
||||
)
|
||||
|
||||
cc = os.environ.get("CC", "gcc")
|
||||
|
||||
# compile the object file to a shared library
|
||||
cmd = [
|
||||
cc,
|
||||
"-shared",
|
||||
"-o",
|
||||
"./build/libexport_example.so",
|
||||
"./build/print_tensor_example.o",
|
||||
"./build/add_one_example.o",
|
||||
]
|
||||
subprocess.run(cmd, check=True)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
run()
|
||||
@@ -0,0 +1,79 @@
|
||||
# Copyright (c) 2025 - 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
|
||||
# 1. Redistributions of source code must retain the above copyright notice, this
|
||||
# list of conditions and the following disclaimer.
|
||||
|
||||
# 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
|
||||
# 3. Neither the name of the copyright holder nor the names of its
|
||||
# contributors may be used to endorse or promote products derived from
|
||||
# this software without specific prior written permission.
|
||||
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
import cutlass
|
||||
import cutlass.cute as cute
|
||||
import cuda.bindings.driver as cuda
|
||||
|
||||
|
||||
"""Example demonstrating how to load a CuTe module/function in Python.
|
||||
|
||||
This example shows how to:
|
||||
1. Load a CuTe module from a object file or a shared library
|
||||
2. Extract the function from the module and call it in Python
|
||||
|
||||
To run this example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
# prerequesites: export the compiled functions to object files and compile them into a shared library
|
||||
python examples/cute/export/export_to_c.py
|
||||
# load the module from a object file or a shared library
|
||||
python examples/cute/export/load_in_python.py
|
||||
"""
|
||||
|
||||
|
||||
def run():
|
||||
import torch
|
||||
from cutlass.cute.runtime import from_dlpack
|
||||
|
||||
a = (
|
||||
torch.arange(16 * 10, dtype=torch.float32, device="cuda")
|
||||
.reshape(16, 10)
|
||||
.permute(1, 0)
|
||||
)
|
||||
b = torch.ones(16, 10, dtype=torch.float32, device="cuda").permute(1, 0)
|
||||
a_cute = from_dlpack(a).mark_layout_dynamic()
|
||||
b_cute = from_dlpack(b).mark_layout_dynamic()
|
||||
stream = cuda.CUstream(0)
|
||||
|
||||
print_tensor_mod = cute.runtime.load_module("./build/print_tensor_example.o")
|
||||
print_tensor_mod.print_tensor(a_cute, stream=stream)
|
||||
|
||||
add_one_mod = cute.runtime.load_module("./build/add_one_example.o")
|
||||
add_one_mod.add_one(a_cute, b_cute, stream=stream)
|
||||
assert a[0, 0] == b[0, 0] + 1
|
||||
|
||||
shared_mod = cute.runtime.load_module("./build/libexport_example.so")
|
||||
shared_mod.print_tensor(a_cute, stream=stream)
|
||||
shared_mod.add_one(a_cute, b_cute, stream=stream)
|
||||
assert a[0, 0] == b[0, 0] + 1
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
run()
|
||||
@@ -0,0 +1,254 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2025 - 2026 NVIDIA CORPORATION & AFFILIATES.
|
||||
* All rights reserved. SPDX-License-Identifier: LicenseRef-NvidiaProprietary
|
||||
*
|
||||
* NVIDIA CORPORATION, its affiliates and licensors retain all intellectual
|
||||
* property and proprietary rights in and to this material, related
|
||||
* documentation and any modifications thereto. Any use, reproduction,
|
||||
* disclosure or distribution of this material and related documentation
|
||||
* without an express license agreement from NVIDIA CORPORATION or
|
||||
* its affiliates is strictly prohibited.
|
||||
*/
|
||||
/**
|
||||
* This example demonstrates how to load a CuTe module/function from a object
|
||||
* file or a shared library and run it in a CUDA kernel.
|
||||
*
|
||||
* To run this example:
|
||||
*
|
||||
* .. code-block:: bash
|
||||
*
|
||||
* # prerequesites: export the compiled functions to object files and compile
|
||||
* them into a shared library python examples/cute/export/export_to_c.py # run
|
||||
* the example bash ./examples/cute/export/run_with_dynamic_loading.sh
|
||||
*/
|
||||
|
||||
#include "CuteDSLRuntime.h"
|
||||
#include <cuda_runtime.h>
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
|
||||
std::vector<unsigned char> read_file(const std::string &filename) {
|
||||
std::ifstream file(filename, std::ios::binary);
|
||||
std::vector<unsigned char> content((std::istreambuf_iterator<char>(file)),
|
||||
std::istreambuf_iterator<char>());
|
||||
return content;
|
||||
}
|
||||
|
||||
void initialize_cuda_context() {
|
||||
// Initialize cuda context
|
||||
cudaSetDevice(0);
|
||||
}
|
||||
|
||||
void check_error(CuteDSLRT_Error_t error) {
|
||||
if (error != CuteDSLRT_Error_Success) {
|
||||
printf("Got runtime error: %d\n", error);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// Copy the definition of the tensor from `print_tensor_example.h` to here
|
||||
typedef struct {
|
||||
void *data;
|
||||
int32_t dynamic_shapes[2];
|
||||
int64_t dynamic_strides[1];
|
||||
} print_tensor_Tensor_a_t;
|
||||
|
||||
// Copy the definition of the tensor from `add_one_example.h` to here
|
||||
typedef struct {
|
||||
void *data;
|
||||
int32_t dynamic_shapes[2];
|
||||
int64_t dynamic_strides[1];
|
||||
} add_one_Tensor_a_t;
|
||||
typedef struct {
|
||||
void *data;
|
||||
int32_t dynamic_shapes[2];
|
||||
int64_t dynamic_strides[1];
|
||||
} add_one_Tensor_b_t;
|
||||
|
||||
print_tensor_Tensor_a_t prepare_print_tensor_tensor() {
|
||||
print_tensor_Tensor_a_t tensor;
|
||||
tensor.data = NULL;
|
||||
tensor.dynamic_shapes[0] = 32;
|
||||
tensor.dynamic_shapes[1] = 16;
|
||||
tensor.dynamic_strides[0] = 16;
|
||||
return tensor;
|
||||
}
|
||||
|
||||
add_one_Tensor_a_t prepare_add_one_tensor_a() {
|
||||
float a_host_ptr[32 * 16];
|
||||
for (int i = 0; i < 32 * 16; i++) {
|
||||
a_host_ptr[i] = i;
|
||||
}
|
||||
void *a_device_ptr;
|
||||
cudaMalloc(&a_device_ptr, sizeof(float) * 32 * 16);
|
||||
cudaMemcpy(a_device_ptr, a_host_ptr, sizeof(float) * 32 * 16,
|
||||
cudaMemcpyHostToDevice);
|
||||
add_one_Tensor_a_t tensor;
|
||||
tensor.data = (void *)a_device_ptr;
|
||||
tensor.dynamic_shapes[0] = 32;
|
||||
tensor.dynamic_shapes[1] = 16;
|
||||
tensor.dynamic_strides[0] = 16;
|
||||
return tensor;
|
||||
}
|
||||
|
||||
add_one_Tensor_b_t prepare_add_one_tensor_b() {
|
||||
float b_host_ptr[32 * 16];
|
||||
for (int i = 0; i < 32 * 16; i++) {
|
||||
b_host_ptr[i] = 32 * 16 - i;
|
||||
}
|
||||
void *b_device_ptr;
|
||||
cudaMalloc(&b_device_ptr, sizeof(float) * 32 * 16);
|
||||
cudaMemcpy(b_device_ptr, b_host_ptr, sizeof(float) * 32 * 16,
|
||||
cudaMemcpyHostToDevice);
|
||||
add_one_Tensor_b_t tensor;
|
||||
tensor.data = (void *)b_device_ptr;
|
||||
tensor.dynamic_shapes[0] = 32;
|
||||
tensor.dynamic_shapes[1] = 16;
|
||||
tensor.dynamic_strides[0] = 16;
|
||||
return tensor;
|
||||
}
|
||||
|
||||
void run_print_tensor_with_object_file() {
|
||||
|
||||
// prepare tensor
|
||||
print_tensor_Tensor_a_t tensor = prepare_print_tensor_tensor();
|
||||
|
||||
// prepare stream
|
||||
cudaStream_t stream;
|
||||
cudaStreamCreate(&stream);
|
||||
|
||||
// load module and function
|
||||
CuteDSLRT_Module_t *module = nullptr;
|
||||
std::vector<unsigned char> print_tensor_example_o_bytes =
|
||||
read_file("build/print_tensor_example.o");
|
||||
size_t print_tensor_example_o_size = print_tensor_example_o_bytes.size();
|
||||
CuteDSLRT_Error_t error = CuteDSLRT_Module_Create_From_Bytes(
|
||||
&module, print_tensor_example_o_bytes.data(), print_tensor_example_o_size,
|
||||
nullptr, 0);
|
||||
check_error(error);
|
||||
|
||||
CuteDSLRT_Function_t *function = nullptr;
|
||||
error = CuteDSLRT_Module_Get_Function(&function, module, "print_tensor");
|
||||
check_error(error);
|
||||
|
||||
// run kernel, refer to the wrapper function in `print_tensor_example.h`
|
||||
int32_t cuda_result;
|
||||
void *args[3] = {&tensor, &stream, &cuda_result};
|
||||
error = CuteDSLRT_Function_Run(function, args, 3);
|
||||
check_error(error);
|
||||
|
||||
// synchronize stream
|
||||
cudaStreamSynchronize(stream);
|
||||
|
||||
// unload module
|
||||
error = CuteDSLRT_Module_Destroy(module);
|
||||
check_error(error);
|
||||
cudaStreamDestroy(stream);
|
||||
}
|
||||
|
||||
void run_add_one_with_object_file() {
|
||||
// prepare a tensor
|
||||
add_one_Tensor_a_t tensor_a = prepare_add_one_tensor_a();
|
||||
|
||||
// prepare b tensor
|
||||
add_one_Tensor_b_t tensor_b = prepare_add_one_tensor_b();
|
||||
|
||||
// prepare stream
|
||||
cudaStream_t stream;
|
||||
cudaStreamCreate(&stream);
|
||||
|
||||
// load module
|
||||
CuteDSLRT_Module_t *module = nullptr;
|
||||
std::vector<unsigned char> add_one_example_o_bytes =
|
||||
read_file("build/add_one_example.o");
|
||||
size_t add_one_example_o_size = add_one_example_o_bytes.size();
|
||||
CuteDSLRT_Error_t error = CuteDSLRT_Module_Create_From_Bytes(
|
||||
&module, add_one_example_o_bytes.data(), add_one_example_o_size, nullptr,
|
||||
0);
|
||||
check_error(error);
|
||||
|
||||
CuteDSLRT_Function_t *function = nullptr;
|
||||
error = CuteDSLRT_Module_Get_Function(&function, module, "add_one");
|
||||
check_error(error);
|
||||
|
||||
// run kernel, refer to the wrapper function in `add_one_example.h`
|
||||
int32_t cuda_result;
|
||||
void *args[4] = {&tensor_a, &tensor_b, &stream, &cuda_result};
|
||||
error = CuteDSLRT_Function_Run(function, args, 4);
|
||||
check_error(error);
|
||||
cudaStreamSynchronize(stream);
|
||||
|
||||
// unload module
|
||||
error = CuteDSLRT_Module_Destroy(module);
|
||||
check_error(error);
|
||||
cudaStreamDestroy(stream);
|
||||
|
||||
// check result
|
||||
float a_host_ptr[32 * 16];
|
||||
cudaMemcpy(a_host_ptr, tensor_a.data, sizeof(float) * 32 * 16,
|
||||
cudaMemcpyDeviceToHost);
|
||||
|
||||
if (a_host_ptr[0] != 32 * 16 + 1) {
|
||||
printf("Error: a_host_ptr[0] = %f, expected %d\n", a_host_ptr[0], 32 * 16);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
void run_example_with_shared_library() {
|
||||
// prepare tensor
|
||||
print_tensor_Tensor_a_t tensor = prepare_print_tensor_tensor();
|
||||
|
||||
// prepare a tensor
|
||||
add_one_Tensor_a_t tensor_a = prepare_add_one_tensor_a();
|
||||
|
||||
// prepare b tensor
|
||||
add_one_Tensor_b_t tensor_b = prepare_add_one_tensor_b();
|
||||
|
||||
// prepare stream
|
||||
cudaStream_t stream;
|
||||
cudaStreamCreate(&stream);
|
||||
|
||||
// load module
|
||||
CuteDSLRT_Module_t *module = nullptr;
|
||||
const char *shared_libs[] = {"build/libexport_example.so"};
|
||||
CuteDSLRT_Error_t error =
|
||||
CuteDSLRT_Module_Create_From_Bytes(&module, nullptr, 0, shared_libs, 1);
|
||||
check_error(error);
|
||||
|
||||
// get print tensor function
|
||||
CuteDSLRT_Function_t *print_tensor_function = nullptr;
|
||||
error = CuteDSLRT_Module_Get_Function(&print_tensor_function, module,
|
||||
"print_tensor");
|
||||
check_error(error);
|
||||
|
||||
// get add one function
|
||||
CuteDSLRT_Function_t *add_one_function = nullptr;
|
||||
error = CuteDSLRT_Module_Get_Function(&add_one_function, module, "add_one");
|
||||
check_error(error);
|
||||
|
||||
// run print tensor kernel
|
||||
int32_t cuda_result;
|
||||
void *print_tensor_args[3] = {&tensor, &stream, &cuda_result};
|
||||
error = CuteDSLRT_Function_Run(print_tensor_function, print_tensor_args, 3);
|
||||
check_error(error);
|
||||
cudaStreamSynchronize(stream);
|
||||
|
||||
// run add one kernel
|
||||
void *add_one_args[4] = {&tensor_a, &tensor_b, &stream, &cuda_result};
|
||||
error = CuteDSLRT_Function_Run(add_one_function, add_one_args, 4);
|
||||
check_error(error);
|
||||
cudaStreamSynchronize(stream);
|
||||
|
||||
// unload module
|
||||
error = CuteDSLRT_Module_Destroy(module);
|
||||
check_error(error);
|
||||
cudaStreamDestroy(stream);
|
||||
}
|
||||
|
||||
int main() {
|
||||
initialize_cuda_context();
|
||||
run_print_tensor_with_object_file();
|
||||
run_add_one_with_object_file();
|
||||
run_example_with_shared_library();
|
||||
return 0;
|
||||
}
|
||||
80
examples/python/CuTeDSL/dsl_tutorials/export/run_with_dynamic_loading.sh
Executable file
80
examples/python/CuTeDSL/dsl_tutorials/export/run_with_dynamic_loading.sh
Executable file
@@ -0,0 +1,80 @@
|
||||
# Copyright (c) 2025 - 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
|
||||
# 1. Redistributions of source code must retain the above copyright notice, this
|
||||
# list of conditions and the following disclaimer.
|
||||
|
||||
# 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
|
||||
# 3. Neither the name of the copyright holder nor the names of its
|
||||
# contributors may be used to endorse or promote products derived from
|
||||
# this software without specific prior written permission.
|
||||
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#!/bin/bash
|
||||
set -eu
|
||||
|
||||
# Try to find the wheel path of nvidia-cutlass-dsl
|
||||
WHEEL_PATH=$(python3 -c "import cutlass, os; print(os.path.dirname(cutlass.__file__))" 2>/dev/null)/../..
|
||||
|
||||
if [[ -z "$WHEEL_PATH" ]]; then
|
||||
echo "nvidia-cutlass-dsl wheel not found in the current Python environment."
|
||||
exit 1
|
||||
else
|
||||
echo "nvidia-cutlass-dsl wheel path found at: $WHEEL_PATH"
|
||||
fi
|
||||
|
||||
CUTE_DSL_LIB_PATH="${WHEEL_PATH}/lib/"
|
||||
export LD_LIBRARY_PATH=${CUTE_DSL_LIB_PATH}:${CUDA_HOME}/lib64:./build
|
||||
|
||||
if [ -z "$CUDA_HOME" ]; then
|
||||
CUDA_HOME=/usr/local/cuda
|
||||
echo "CUDA_HOME not set, using default: $CUDA_HOME"
|
||||
else
|
||||
echo "CUDA_HOME found: $CUDA_HOME"
|
||||
fi
|
||||
SOURCE_FILE="$(dirname "$0")/run_with_dynamic_loading.cpp"
|
||||
|
||||
echo "Compiling the executable..."
|
||||
# Search for a common C++ compiler: g++, clang++, or c++
|
||||
if [ -n "${CXX-}" ] && command -v "$CXX" &> /dev/null; then
|
||||
CXX="$CXX"
|
||||
elif command -v g++ &> /dev/null; then
|
||||
CXX="g++"
|
||||
elif command -v clang++ &> /dev/null; then
|
||||
CXX="clang++"
|
||||
elif command -v c++ &> /dev/null; then
|
||||
CXX="c++"
|
||||
else
|
||||
echo "Error: No common C++ compiler found (g++, clang++, or c++). Please install a C++ compiler to continue."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
$CXX -o build/run_with_dynamic_loading \
|
||||
-I${CUDA_HOME}/include \
|
||||
-I${WHEEL_PATH}/include \
|
||||
${SOURCE_FILE} \
|
||||
-L${CUTE_DSL_LIB_PATH} \
|
||||
-L${CUDA_HOME}/lib64 \
|
||||
-L./build \
|
||||
-lcudart \
|
||||
-lcute_dsl_runtime \
|
||||
-lexport_example
|
||||
|
||||
echo "Running the executable..."
|
||||
./build/run_with_dynamic_loading
|
||||
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2025 - 2026 NVIDIA CORPORATION & AFFILIATES.
|
||||
* All rights reserved. SPDX-License-Identifier: LicenseRef-NvidiaProprietary
|
||||
*
|
||||
* NVIDIA CORPORATION, its affiliates and licensors retain all intellectual
|
||||
* property and proprietary rights in and to this material, related
|
||||
* documentation and any modifications thereto. Any use, reproduction,
|
||||
* disclosure or distribution of this material and related documentation
|
||||
* without an express license agreement from NVIDIA CORPORATION or
|
||||
* its affiliates is strictly prohibited.
|
||||
*/
|
||||
/**
|
||||
* This example demonstrates how to load a CuTe module/function from compilation
|
||||
* and static linking and run it in a CUDA kernel.
|
||||
*
|
||||
* To run this example:
|
||||
*
|
||||
* .. code-block:: bash
|
||||
*
|
||||
* # prerequesites: export the compiled functions to object files and compile
|
||||
* them into a shared library python examples/cute/export/export_to_c.py # run
|
||||
* the example bash ./examples/cute/export/run_with_static_linking.sh
|
||||
*/
|
||||
|
||||
#include "add_one_example.h"
|
||||
#include "print_tensor_example.h"
|
||||
#include <cuda_runtime.h>
|
||||
|
||||
void initialize_cuda_context() {
|
||||
// Initialize cuda context
|
||||
int device_id = 0;
|
||||
cudaSetDevice(device_id);
|
||||
}
|
||||
|
||||
void run_print_tensor() {
|
||||
// prepare tensor
|
||||
print_tensor_Tensor_a_t tensor;
|
||||
tensor.data = NULL;
|
||||
tensor.dynamic_shapes[0] = 32;
|
||||
tensor.dynamic_shapes[1] = 16;
|
||||
tensor.dynamic_strides[0] = 16;
|
||||
|
||||
// prepare stream
|
||||
cudaStream_t stream;
|
||||
cudaStreamCreate(&stream);
|
||||
|
||||
// load module
|
||||
print_tensor_Kernel_Module_t module;
|
||||
print_tensor_Kernel_Module_Load(&module);
|
||||
|
||||
// run kernel
|
||||
cute_dsl_print_tensor_wrapper(&module, &tensor, stream);
|
||||
|
||||
// synchronize stream
|
||||
cudaStreamSynchronize(stream);
|
||||
|
||||
// unload module
|
||||
print_tensor_Kernel_Module_Unload(&module);
|
||||
cudaStreamDestroy(stream);
|
||||
}
|
||||
|
||||
void run_add_one() {
|
||||
// prepare a tensor
|
||||
add_one_Tensor_a_t a_tensor;
|
||||
float a_host_ptr[32 * 16];
|
||||
for (int i = 0; i < 32 * 16; i++) {
|
||||
a_host_ptr[i] = i;
|
||||
}
|
||||
void *a_device_ptr;
|
||||
cudaMalloc(&a_device_ptr, sizeof(float) * 32 * 16);
|
||||
cudaMemcpy(a_device_ptr, a_host_ptr, sizeof(float) * 32 * 16,
|
||||
cudaMemcpyHostToDevice);
|
||||
a_tensor.data = (void *)a_device_ptr;
|
||||
a_tensor.dynamic_shapes[0] = 32;
|
||||
a_tensor.dynamic_shapes[1] = 16;
|
||||
a_tensor.dynamic_strides[0] = 16;
|
||||
|
||||
// prepare b tensor
|
||||
add_one_Tensor_b_t b_tensor;
|
||||
float b_host_ptr[32 * 16];
|
||||
for (int i = 0; i < 32 * 16; i++) {
|
||||
b_host_ptr[i] = 32 * 16 - i;
|
||||
}
|
||||
void *b_device_ptr;
|
||||
cudaMalloc(&b_device_ptr, sizeof(float) * 32 * 16);
|
||||
cudaMemcpy(b_device_ptr, b_host_ptr, sizeof(float) * 32 * 16,
|
||||
cudaMemcpyHostToDevice);
|
||||
|
||||
b_tensor.data = (void *)b_device_ptr;
|
||||
b_tensor.dynamic_shapes[0] = 32;
|
||||
b_tensor.dynamic_shapes[1] = 16;
|
||||
b_tensor.dynamic_strides[0] = 16;
|
||||
|
||||
// prepare stream
|
||||
cudaStream_t stream;
|
||||
cudaStreamCreate(&stream);
|
||||
|
||||
// load module
|
||||
add_one_Kernel_Module_t module;
|
||||
add_one_Kernel_Module_Load(&module);
|
||||
|
||||
// run kernel
|
||||
cute_dsl_add_one_wrapper(&module, &a_tensor, &b_tensor, stream);
|
||||
cudaStreamSynchronize(stream);
|
||||
|
||||
// unload module
|
||||
add_one_Kernel_Module_Unload(&module);
|
||||
cudaStreamDestroy(stream);
|
||||
|
||||
// check result
|
||||
cudaMemcpy(a_host_ptr, a_device_ptr, sizeof(float) * 32 * 16,
|
||||
cudaMemcpyDeviceToHost);
|
||||
|
||||
if (a_host_ptr[0] != 32 * 16 + 1) {
|
||||
printf("Error: a_host_ptr[0] = %f, expected %d\n", a_host_ptr[0], 32 * 16);
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
initialize_cuda_context();
|
||||
run_print_tensor();
|
||||
run_add_one();
|
||||
return 0;
|
||||
}
|
||||
76
examples/python/CuTeDSL/dsl_tutorials/export/run_with_static_linking.sh
Executable file
76
examples/python/CuTeDSL/dsl_tutorials/export/run_with_static_linking.sh
Executable file
@@ -0,0 +1,76 @@
|
||||
# Copyright (c) 2025 - 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
|
||||
# 1. Redistributions of source code must retain the above copyright notice, this
|
||||
# list of conditions and the following disclaimer.
|
||||
|
||||
# 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
|
||||
# 3. Neither the name of the copyright holder nor the names of its
|
||||
# contributors may be used to endorse or promote products derived from
|
||||
# this software without specific prior written permission.
|
||||
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#!/bin/bash
|
||||
set -eu
|
||||
|
||||
# Try to find the wheel path of nvidia-cutlass-dsl
|
||||
WHEEL_PATH=$(python3 -c "import cutlass, os; print(os.path.dirname(cutlass.__file__))" 2>/dev/null)/../..
|
||||
|
||||
if [[ -z "$WHEEL_PATH" ]]; then
|
||||
echo "nvidia-cutlass-dsl wheel not found in the current Python environment."
|
||||
exit 1
|
||||
else
|
||||
echo "nvidia-cutlass-dsl wheel path found at: $WHEEL_PATH"
|
||||
fi
|
||||
CUTE_DSL_LIB_PATH="${WHEEL_PATH}/lib/"
|
||||
export LD_LIBRARY_PATH=${CUTE_DSL_LIB_PATH}
|
||||
|
||||
if [ -z "$CUDA_HOME" ]; then
|
||||
CUDA_HOME=/usr/local/cuda
|
||||
echo "CUDA_HOME not set, using default: $CUDA_HOME"
|
||||
else
|
||||
echo "CUDA_HOME found: $CUDA_HOME"
|
||||
fi
|
||||
SOURCE_FILE="$(dirname "$0")/run_with_static_linking.cpp"
|
||||
|
||||
echo "Compiling the executable..."
|
||||
# Search for a common C++ compiler: g++, clang++, or c++
|
||||
if [ -n "${CXX-}" ] && command -v "$CXX" &> /dev/null; then
|
||||
CXX="$CXX"
|
||||
elif command -v g++ &> /dev/null; then
|
||||
CXX="g++"
|
||||
elif command -v clang++ &> /dev/null; then
|
||||
CXX="clang++"
|
||||
elif command -v c++ &> /dev/null; then
|
||||
CXX="c++"
|
||||
else
|
||||
echo "Error: No common C++ compiler found (g++, clang++, or c++). Please install a C++ compiler to continue."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Note: The options -ldl, -lrt, and -lpthread are optional to satisfy symbol dependencies required by `libcudart_static.a`.
|
||||
$CXX -o build/run_with_static_linking \
|
||||
-I${CUDA_HOME}/include \
|
||||
-I./build \
|
||||
${SOURCE_FILE} build/add_one_example.o build/print_tensor_example.o \
|
||||
${CUTE_DSL_LIB_PATH}/libcuda_dialect_runtime_static.a \
|
||||
${CUDA_HOME}/lib64/libcudart_static.a -ldl -lrt -lpthread
|
||||
|
||||
echo "Running the executable..."
|
||||
./build/run_with_static_linking
|
||||
Reference in New Issue
Block a user