[CCCL] 瘦身 + 补全: 移除 cudax/python/libcudacxx-tests 冗余文件, 新增 c2h 测试助手 + cmake 构建系统 + 8 个 CUDA thrust examples
变更摘要:
- 删除: cudax/ (783 files, 7.2M) — 实验性组件,竞赛不需要
- 删除: python/ (226 files, 2.0M) — Python 绑定,竞赛不需要
- 删除: libcudacxx/{test,benchmarks,codegen,cmake,share} (4432 files, 31M)
保留: libcudacxx/include/ (1463 headers, cuda::std 编译依赖)
- 新增: c2h/ (27 files) — CUB Catch2 测试辅助头文件,编译 243 个测试必需
- 新增: cmake/ (29 files) — CCCL 原生 CMake 构建系统
- 新增: thrust/examples/cuda/ (7 files) + cpp_integration/ (1 file)
async_reduce, custom_temporary_allocation, explicit_cuda_stream,
global_device_vector, range_view, unwrap_pointer, wrap_pointer, device
结果: cccl_upstream 从 74M→35M (瘦身 53%), 核心内容 100% 保留:
27/27 tuning headers, 78 benchmarks, 243 tests,
60 thrust examples, 18 CUB examples, 全部编译头文件
This commit is contained in:
@@ -1,42 +0,0 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of CUDASTF in CUDA C++ Core Libraries,
|
||||
// under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
// SPDX-FileCopyrightText: Copyright (c) 2022-2024 NVIDIA CORPORATION & AFFILIATES.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include <cuda/experimental/__places/place_partition.cuh>
|
||||
#include <cuda/experimental/__stf/internal/stf_places_partition_into_stf.cuh>
|
||||
#include <cuda/experimental/stf.cuh>
|
||||
|
||||
using namespace cuda::experimental::stf;
|
||||
|
||||
#if _CCCL_CTK_AT_LEAST(12, 4)
|
||||
/**
|
||||
* @brief Test green context partition and affinity: partition by green_context, push/pop affinity per subplace.
|
||||
*/
|
||||
void test_green_ctx_affinity()
|
||||
{
|
||||
async_resources_handle handle;
|
||||
for (auto p : place_partition(exec_place::current_device(), handle, place_partition_scope::green_context))
|
||||
{
|
||||
handle.push_affinity(::std::make_shared<exec_place>(p));
|
||||
_CCCL_ASSERT(handle.current_affinity().size() == 1, "invalid value");
|
||||
handle.pop_affinity();
|
||||
}
|
||||
}
|
||||
#endif // _CCCL_CTK_AT_LEAST(12, 4)
|
||||
|
||||
int main()
|
||||
{
|
||||
#if _CCCL_CTK_BELOW(12, 4)
|
||||
fprintf(stderr, "Green contexts are not supported by this version of CUDA: skipping test.\n");
|
||||
return 0;
|
||||
#else // ^^^ _CCCL_CTK_BELOW(12, 4) ^^^ / vvv _CCCL_CTK_AT_LEAST(12, 4) vvv
|
||||
test_green_ctx_affinity();
|
||||
return 0;
|
||||
#endif // ^^^ _CCCL_CTK_AT_LEAST(12, 4) ^^^
|
||||
}
|
||||
@@ -1,75 +0,0 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of CUDASTF in CUDA C++ Core Libraries,
|
||||
// under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
// SPDX-FileCopyrightText: Copyright (c) 2022-2024 NVIDIA CORPORATION & AFFILIATES.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @brief An AXPY kernel using an exec place attached to a specific CUDA stream
|
||||
*
|
||||
*/
|
||||
|
||||
#include <cuda/experimental/stf.cuh>
|
||||
|
||||
#include "nvtx3/nvToolsExtCudaRt.h"
|
||||
|
||||
using namespace cuda::experimental::stf;
|
||||
|
||||
double X0(size_t i)
|
||||
{
|
||||
return sin((double) i);
|
||||
}
|
||||
|
||||
double Y0(size_t i)
|
||||
{
|
||||
return cos((double) i);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
cudaStream_t stream;
|
||||
cuda_safe_call(cudaStreamCreate(&stream));
|
||||
nvtxNameCudaStreamA(stream, "user stream");
|
||||
|
||||
// context ctx;
|
||||
stream_ctx ctx;
|
||||
const size_t N = 16;
|
||||
double X[N], Y[N];
|
||||
|
||||
for (size_t i = 0; i < N; i++)
|
||||
{
|
||||
X[i] = X0(i);
|
||||
Y[i] = Y0(i);
|
||||
}
|
||||
|
||||
double alpha = 3.14;
|
||||
|
||||
auto lX = ctx.logical_data(X);
|
||||
auto lY = ctx.logical_data(Y);
|
||||
|
||||
/* Compute Y = Y + alpha X on the user stream */
|
||||
auto where = exec_place::cuda_stream(stream);
|
||||
|
||||
for (size_t iter = 0; iter < 20; iter++)
|
||||
{
|
||||
ctx.parallel_for(where, lX.shape(), lX.read(), lY.rw())->*[alpha] __device__(size_t i, auto x, auto y) {
|
||||
y(i) += alpha * x(i);
|
||||
};
|
||||
}
|
||||
|
||||
ctx.finalize();
|
||||
|
||||
for (size_t i = 0; i < N; i++)
|
||||
{
|
||||
assert(fabs(Y[i] - (Y0(i) + 2 * 10.0 * alpha * X0(i))) < 0.0001);
|
||||
assert(fabs(X[i] - X0(i)) < 0.0001);
|
||||
}
|
||||
|
||||
cuda_safe_call(cudaStreamDestroy(stream));
|
||||
}
|
||||
@@ -1,294 +0,0 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of CUDASTF in CUDA C++ Core Libraries,
|
||||
// under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @brief parallel_for over a grid driven by a cute_partition instance
|
||||
*
|
||||
* The same user-facing parallel_for entry point accepts value-defined
|
||||
* partitioners: the partition decides both the kernel decomposition
|
||||
* (per-place sub-shapes) and the data placement (composite data place backed
|
||||
* by the partition).
|
||||
*/
|
||||
|
||||
#include <cuda/experimental/__stf/graph/graph_ctx.cuh>
|
||||
#include <cuda/experimental/__stf/localization/composite_slice.cuh>
|
||||
#include <cuda/experimental/__stf/stream/stream_ctx.cuh>
|
||||
|
||||
using namespace cuda::experimental::stf;
|
||||
|
||||
namespace
|
||||
{
|
||||
void test_cute_composite_cache(const exec_place& grid)
|
||||
{
|
||||
const size_t n = 4096;
|
||||
const dim4 data_dims(n);
|
||||
const auto part = make_partition(data_dims, partition_spec{blocked<0>}, grid.get_dims());
|
||||
const auto place = cuda::experimental::places::make_composite_data_place(grid, part);
|
||||
const auto delinearize = [data_dims](size_t ind) {
|
||||
return data_dims.index_to_pos(ind);
|
||||
};
|
||||
|
||||
reserved::composite_slice_cache cache;
|
||||
|
||||
// Equal element counts are insufficient: a different tensor shape changes
|
||||
// delinearization and therefore ownership.
|
||||
const dim4 mismatched_dims(n / 2, 2);
|
||||
const auto mismatched_delinearize = [mismatched_dims](size_t ind) {
|
||||
return mismatched_dims.index_to_pos(ind);
|
||||
};
|
||||
bool mismatch_thrown = false;
|
||||
try
|
||||
{
|
||||
(void) cache.get(place, mismatched_delinearize, n, sizeof(size_t), mismatched_dims);
|
||||
}
|
||||
catch (const ::std::invalid_argument&)
|
||||
{
|
||||
mismatch_thrown = true;
|
||||
}
|
||||
EXPECT(mismatch_thrown);
|
||||
|
||||
auto [first, first_prereqs] = cache.get(place, delinearize, n, sizeof(size_t), data_dims);
|
||||
EXPECT(first_prereqs.empty());
|
||||
const auto first_base = first->get_base_ptr();
|
||||
|
||||
cache.put(place, mv(first), first_prereqs, n, sizeof(size_t), data_dims);
|
||||
|
||||
// A separately constructed but equivalent place must find the same cached
|
||||
// VMM allocation through the value-keyed CuTe pool.
|
||||
const auto equivalent_part = make_partition(data_dims, partition_spec{blocked<0>}, grid.get_dims());
|
||||
const auto equivalent_place = cuda::experimental::places::make_composite_data_place(grid, equivalent_part);
|
||||
auto [second, second_prereqs] = cache.get(equivalent_place, delinearize, n, sizeof(size_t), data_dims);
|
||||
EXPECT(second_prereqs.empty());
|
||||
EXPECT(second->get_base_ptr() == first_base);
|
||||
|
||||
cache.put(equivalent_place, mv(second), second_prereqs, n, sizeof(size_t), data_dims);
|
||||
EXPECT(cache.deinit().empty());
|
||||
}
|
||||
|
||||
void test_static_codegen_parity(stream_ctx& ctx, const exec_place& grid)
|
||||
{
|
||||
const size_t nx = 64;
|
||||
const size_t ny = 32;
|
||||
auto typed_data = ctx.logical_data(shape_of<slice<size_t, 2>>(nx, ny));
|
||||
auto classic_data = ctx.logical_data(shape_of<slice<size_t, 2>>(nx, ny));
|
||||
const auto part = make_partition(dim4(nx, ny), partition_spec{whole, blocked<0>}, grid.get_dims());
|
||||
auto write = [] _CCCL_DEVICE(size_t x, size_t y, auto values) {
|
||||
values(x, y) = x + 100 * y;
|
||||
};
|
||||
|
||||
ctx.parallel_for(part, grid, typed_data.shape(), typed_data.write())->*decltype(write)(write);
|
||||
ctx.parallel_for(blocked_partition(), grid, classic_data.shape(), classic_data.write())->*decltype(write)(write);
|
||||
|
||||
ctx.host_launch(typed_data.read(), classic_data.read())->*[=](auto typed, auto classic) {
|
||||
for (size_t y = 0; y < ny; y++)
|
||||
{
|
||||
for (size_t x = 0; x < nx; x++)
|
||||
{
|
||||
EXPECT(typed(x, y) == x + 100 * y);
|
||||
EXPECT(classic(x, y) == typed(x, y));
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
void test_cute_graph_backend(const exec_place& grid)
|
||||
{
|
||||
const size_t n = 1023;
|
||||
graph_ctx ctx;
|
||||
auto data = ctx.logical_data(shape_of<slice<size_t>>(n));
|
||||
const auto part = make_partition(dim4(n), partition_spec{blocked<0>}, grid.get_dims());
|
||||
|
||||
ctx.parallel_for(part, grid, data.shape(), data.write())->*[] _CCCL_DEVICE(size_t i, auto values) {
|
||||
values(i) = 5 * i + 3;
|
||||
};
|
||||
ctx.host_launch(data.read())->*[=](auto values) {
|
||||
for (size_t i = 0; i < n; i++)
|
||||
{
|
||||
EXPECT(values(i) == 5 * i + 3);
|
||||
}
|
||||
};
|
||||
ctx.finalize();
|
||||
}
|
||||
} // namespace
|
||||
|
||||
int main()
|
||||
{
|
||||
int ndevs;
|
||||
cuda_safe_call(cudaGetDeviceCount(&ndevs));
|
||||
|
||||
stream_ctx ctx;
|
||||
|
||||
// A grid of two places (same device when only one GPU is present)
|
||||
::std::vector<exec_place> places;
|
||||
places.push_back(exec_place::device(0));
|
||||
places.push_back(exec_place::device(ndevs > 1 ? 1 : 0));
|
||||
auto grid = make_grid(mv(places));
|
||||
|
||||
test_cute_composite_cache(grid);
|
||||
test_static_codegen_parity(ctx, grid);
|
||||
|
||||
// 1-D: dimension 0 blocked over the grid
|
||||
{
|
||||
const size_t n = 1024 * 1024;
|
||||
auto lA = ctx.logical_data(shape_of<slice<size_t>>(n));
|
||||
|
||||
auto part = make_partition(dim4(n), partition_spec{blocked<0>}, grid.get_dims());
|
||||
|
||||
ctx.parallel_for(part, grid, lA.shape(), lA.write())->*[] _CCCL_DEVICE(size_t i, auto a) {
|
||||
a(i) = 3 * i + 7;
|
||||
};
|
||||
|
||||
ctx.host_launch(lA.read())->*[&](auto a) {
|
||||
for (size_t i = 0; i < n; i++)
|
||||
{
|
||||
EXPECT(a(i) == 3 * i + 7);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// 3-D: dimension 1 blocked over the grid (the per-dimension expressiveness
|
||||
// the classic blocked_partition cannot provide)
|
||||
{
|
||||
const size_t nx = 32, ny = 64, nz = 16;
|
||||
auto lB = ctx.logical_data(shape_of<slice<size_t, 3>>(nx, ny, nz));
|
||||
|
||||
auto part = make_partition(dim4(nx, ny, nz), partition_spec{whole, blocked<0>, whole}, grid.get_dims());
|
||||
|
||||
ctx.parallel_for(part, grid, lB.shape(), lB.write())->*[] _CCCL_DEVICE(size_t x, size_t y, size_t z, auto b) {
|
||||
b(x, y, z) = x + 100 * y + 10000 * z;
|
||||
};
|
||||
|
||||
ctx.host_launch(lB.read())->*[&](auto b) {
|
||||
for (size_t x = 0; x < nx; x++)
|
||||
{
|
||||
for (size_t y = 0; y < ny; y++)
|
||||
{
|
||||
for (size_t z = 0; z < nz; z++)
|
||||
{
|
||||
EXPECT(b(x, y, z) == x + 100 * y + 10000 * z);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// The classic stateless partitioners keep working through the same entry
|
||||
{
|
||||
const size_t n = 4096;
|
||||
auto lC = ctx.logical_data(shape_of<slice<size_t>>(n));
|
||||
|
||||
ctx.parallel_for(blocked_partition(), grid, lC.shape(), lC.write())->*[] _CCCL_DEVICE(size_t i, auto c) {
|
||||
c(i) = i;
|
||||
};
|
||||
|
||||
ctx.host_launch(lC.read())->*[&](auto c) {
|
||||
for (size_t i = 0; i < n; i++)
|
||||
{
|
||||
EXPECT(c(i) == i);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Uneven extents: the padding phantoms are excluded by the sub-shape's
|
||||
// predicate (CuTe predication), so odd sizes work end to end
|
||||
{
|
||||
const size_t n = 1023; // not divisible by 2 places
|
||||
auto lD = ctx.logical_data(shape_of<slice<size_t>>(n));
|
||||
|
||||
auto part = make_partition(dim4(n), partition_spec{blocked<0>}, grid.get_dims());
|
||||
|
||||
ctx.parallel_for(part, grid, lD.shape(), lD.write())->*[] _CCCL_DEVICE(size_t i, auto d) {
|
||||
d(i) = 2 * i + 1;
|
||||
};
|
||||
|
||||
ctx.host_launch(lD.read())->*[&](auto d) {
|
||||
for (size_t i = 0; i < n; i++)
|
||||
{
|
||||
EXPECT(d(i) == 2 * i + 1);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Interior region: the box is a region within the tensor the partition was
|
||||
// built for; each place computes its owned coordinates restricted to the
|
||||
// box, and the boundary stays untouched
|
||||
{
|
||||
const size_t nx = 64, ny = 32;
|
||||
auto lE = ctx.logical_data(shape_of<slice<size_t, 2>>(nx, ny));
|
||||
|
||||
auto part = make_partition(dim4(nx, ny), partition_spec{whole, blocked<0>}, grid.get_dims());
|
||||
|
||||
ctx.parallel_for(part, grid, lE.shape(), lE.write())->*[] _CCCL_DEVICE(size_t x, size_t y, auto e) {
|
||||
e(x, y) = 7;
|
||||
};
|
||||
|
||||
box interior({1ul, nx - 1}, {1ul, ny - 1});
|
||||
ctx.parallel_for(part, grid, interior, lE.rw())->*[] _CCCL_DEVICE(size_t x, size_t y, auto e) {
|
||||
e(x, y) = 100 + x + y;
|
||||
};
|
||||
|
||||
ctx.host_launch(lE.read())->*[&](auto e) {
|
||||
for (size_t x = 0; x < nx; x++)
|
||||
{
|
||||
for (size_t y = 0; y < ny; y++)
|
||||
{
|
||||
const bool inside = (x >= 1 && x < nx - 1 && y >= 1 && y < ny - 1);
|
||||
EXPECT(e(x, y) == (inside ? 100 + x + y : 7));
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Boundary-style thin regions: iterate the face with a classic scale-free
|
||||
// partitioner (tight, no discarded lanes) while keeping placement on the
|
||||
// cute composite through explicit deps. This relies on separately
|
||||
// constructed equal partitions producing the same composite identity -
|
||||
// guarded here.
|
||||
{
|
||||
const size_t nx = 64, ny = 32;
|
||||
auto lF = ctx.logical_data(shape_of<slice<size_t, 2>>(nx, ny));
|
||||
|
||||
auto part = make_partition(dim4(nx, ny), partition_spec{whole, blocked<0>}, grid.get_dims());
|
||||
auto dist = cuda::experimental::places::make_composite_data_place(grid, part);
|
||||
const auto equivalent_part = make_partition(dim4(nx, ny), partition_spec{whole, blocked<0>}, grid.get_dims());
|
||||
|
||||
EXPECT(dist == cuda::experimental::places::make_composite_data_place(grid, equivalent_part),
|
||||
"cute composites from equal partitions must compare equal");
|
||||
|
||||
// Volumetric pass placed and decomposed by the partition
|
||||
ctx.parallel_for(part, grid, lF.shape(), lF.write())->*[] _CCCL_DEVICE(size_t x, size_t y, auto f) {
|
||||
f(x, y) = 1;
|
||||
};
|
||||
|
||||
// Face update: classic iteration over the thin box, same placement
|
||||
box face({0ul, nx}, {0ul, 1ul});
|
||||
ctx.parallel_for(blocked_partition(), grid, face, lF.rw(dist))->*[] _CCCL_DEVICE(size_t x, size_t y, auto f) {
|
||||
f(x, y) = 42;
|
||||
};
|
||||
|
||||
ctx.host_launch(lF.read())->*[&](auto f) {
|
||||
for (size_t x = 0; x < nx; x++)
|
||||
{
|
||||
for (size_t y = 0; y < ny; y++)
|
||||
{
|
||||
EXPECT(f(x, y) == (y == 0 ? 42 : 1));
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
ctx.finalize();
|
||||
test_cute_graph_backend(grid);
|
||||
|
||||
printf("cute_parallel_for: all checks passed\n");
|
||||
return 0;
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of CUDASTF in CUDA C++ Core Libraries,
|
||||
// under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
// SPDX-FileCopyrightText: Copyright (c) 2022-2024 NVIDIA CORPORATION & AFFILIATES.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
//! file
|
||||
//! !brief Check that multi-level launch specification are fulfilled
|
||||
|
||||
#include <cuda/experimental/stf.cuh>
|
||||
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
|
||||
using namespace cuda::experimental::stf;
|
||||
|
||||
int main()
|
||||
{
|
||||
stream_ctx ctx;
|
||||
|
||||
// Create a 3-level thread hierarchy specification that would expose the bug:
|
||||
// Level 0: only 1 device to run on CI
|
||||
// Level 1: 4 blocks per device (width 4)
|
||||
// Level 2: 64 threads per block (width 64)
|
||||
//
|
||||
auto spec = par(hw_scope::device, 1, con<4>(hw_scope::block, con<64>(hw_scope::thread)));
|
||||
|
||||
int test_result = 0;
|
||||
auto l_test_result = ctx.logical_data(make_slice(&test_result, 1));
|
||||
|
||||
ctx.launch(spec, exec_place::current_device(), l_test_result.rw())->*[] __device__(auto th, auto result) {
|
||||
if (th.rank() == 0)
|
||||
{
|
||||
bool level0_correct = (th.size(0) == 1); // device level
|
||||
bool level1_correct = (th.size(1) == 1 * 4) && (gridDim.x == 4); // blocks per device
|
||||
bool level2_correct = (th.size(2) == 1 * 4 * 64) && (blockDim.x == 64); // threads per block
|
||||
|
||||
// Set test result based on whether all levels are correct
|
||||
result[0] = level0_correct && level1_correct && level2_correct ? 1 : 0;
|
||||
}
|
||||
};
|
||||
|
||||
ctx.finalize();
|
||||
|
||||
if (test_result != 1)
|
||||
{
|
||||
fprintf(stderr, "FAIL: Hierarchy dimensions are incorrect!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,87 +0,0 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of CUDASTF in CUDA C++ Core Libraries,
|
||||
// under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
// SPDX-FileCopyrightText: Copyright (c) 2022-2024 NVIDIA CORPORATION & AFFILIATES.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @brief An AXPY kernel implemented with a task of the CUDA stream backend
|
||||
* where the task accesses managed memory from the device
|
||||
*
|
||||
*/
|
||||
|
||||
#include <cuda/experimental/__stf/stream/stream_ctx.cuh>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
using namespace cuda::experimental::stf;
|
||||
|
||||
__global__ void axpy(double a, slice<const double> x, slice<double> y)
|
||||
{
|
||||
int tid = blockIdx.x * blockDim.x + threadIdx.x;
|
||||
int nthreads = gridDim.x * blockDim.x;
|
||||
|
||||
for (int i = tid; i < x.size(); i += nthreads)
|
||||
{
|
||||
y(i) += a * x(i);
|
||||
}
|
||||
}
|
||||
|
||||
double X0(size_t i)
|
||||
{
|
||||
return sin((double) i);
|
||||
}
|
||||
|
||||
double Y0(size_t i)
|
||||
{
|
||||
return cos((double) i);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
// Verify whether this device can access memory concurrently from CPU and GPU.
|
||||
int dev;
|
||||
cuda_safe_call(cudaGetDevice(&dev));
|
||||
assert(dev >= 0);
|
||||
cudaDeviceProp prop;
|
||||
cuda_safe_call(cudaGetDeviceProperties(&prop, dev));
|
||||
if (!prop.concurrentManagedAccess)
|
||||
{
|
||||
fprintf(stderr, "Concurrent CPU/GPU access not supported, skipping test.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
stream_ctx ctx;
|
||||
const size_t N = 16;
|
||||
double X[N], Y[N];
|
||||
|
||||
for (size_t i = 0; i < N; i++)
|
||||
{
|
||||
X[i] = X0(i);
|
||||
Y[i] = Y0(i);
|
||||
}
|
||||
|
||||
double alpha = 3.14;
|
||||
|
||||
auto lX = ctx.logical_data(X);
|
||||
auto lY = ctx.logical_data(Y);
|
||||
|
||||
/* Compute Y = Y + alpha X, but leave X on the host and access it with mapped memory */
|
||||
ctx.task(lX.read(data_place::managed()), lY.rw())->*[&](cudaStream_t s, auto dX, auto dY) {
|
||||
axpy<<<16, 128, 0, s>>>(alpha, dX, dY);
|
||||
};
|
||||
|
||||
ctx.finalize();
|
||||
|
||||
for (size_t i = 0; i < N; i++)
|
||||
{
|
||||
assert(fabs(Y[i] - (Y0(i) + alpha * X0(i))) < 0.0001);
|
||||
assert(fabs(X[i] - X0(i)) < 0.0001);
|
||||
}
|
||||
}
|
||||
@@ -1,92 +0,0 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of CUDASTF in CUDA C++ Core Libraries,
|
||||
// under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
// SPDX-FileCopyrightText: Copyright (c) 2022-2024 NVIDIA CORPORATION & AFFILIATES.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @brief Make sure we can automatically allocate and use data in managed memory based on their shape
|
||||
*
|
||||
*/
|
||||
|
||||
#include <cuda/experimental/__stf/stream/stream_ctx.cuh>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
using namespace cuda::experimental::stf;
|
||||
|
||||
__global__ void axpy(double a, slice<const double> x, slice<double> y)
|
||||
{
|
||||
int tid = blockIdx.x * blockDim.x + threadIdx.x;
|
||||
int nthreads = gridDim.x * blockDim.x;
|
||||
|
||||
for (int i = tid; i < x.size(); i += nthreads)
|
||||
{
|
||||
y(i) += a * x(i);
|
||||
}
|
||||
}
|
||||
|
||||
__host__ __device__ double X0(size_t i)
|
||||
{
|
||||
return sin((double) i);
|
||||
}
|
||||
|
||||
double Y0(size_t i)
|
||||
{
|
||||
return cos((double) i);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
// Verify whether this device can access memory concurrently from CPU and GPU.
|
||||
int dev;
|
||||
cuda_safe_call(cudaGetDevice(&dev));
|
||||
assert(dev >= 0);
|
||||
cudaDeviceProp prop;
|
||||
cuda_safe_call(cudaGetDeviceProperties(&prop, dev));
|
||||
if (!prop.concurrentManagedAccess)
|
||||
{
|
||||
fprintf(stderr, "Concurrent CPU/GPU access not supported, skipping test.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
stream_ctx ctx;
|
||||
const size_t N = 16;
|
||||
double Y[N];
|
||||
|
||||
for (size_t i = 0; i < N; i++)
|
||||
{
|
||||
Y[i] = Y0(i);
|
||||
}
|
||||
|
||||
double alpha = 3.14;
|
||||
|
||||
auto lX = ctx.logical_data(shape_of<slice<double>>(N));
|
||||
auto lY = ctx.logical_data(Y);
|
||||
|
||||
// Make sure X is created automatically in managed memory
|
||||
ctx.parallel_for(lX.shape(), lX.write(data_place::managed()))->*[] _CCCL_DEVICE(size_t i, auto X) {
|
||||
X(i) = X0(i);
|
||||
};
|
||||
|
||||
/* Compute Y = Y + alpha X, but leave X in managed memory */
|
||||
ctx.task(lX.read(data_place::managed()), lY.rw())->*[&](cudaStream_t s, auto dX, auto dY) {
|
||||
axpy<<<16, 128, 0, s>>>(alpha, dX, dY);
|
||||
};
|
||||
|
||||
ctx.host_launch(lX.read(data_place::managed()), lY.read())->*[=](auto X, auto Y) {
|
||||
for (size_t i = 0; i < N; i++)
|
||||
{
|
||||
EXPECT(fabs(Y(i) - (Y0(i) + alpha * X0(i))) < 0.0001);
|
||||
EXPECT(fabs(X(i) - X0(i)) < 0.0001);
|
||||
}
|
||||
};
|
||||
|
||||
ctx.finalize();
|
||||
}
|
||||
@@ -1,90 +0,0 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of CUDASTF in CUDA C++ Core Libraries,
|
||||
// under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
// SPDX-FileCopyrightText: Copyright (c) 2022-2024 NVIDIA CORPORATION & AFFILIATES.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @brief An AXPY kernel implemented with a task of the CUDA stream backend
|
||||
* where the task accesses managed memory from the device. This tests
|
||||
* explicitly created managed memory, and passes it to a logical data.
|
||||
*/
|
||||
|
||||
#include <cuda/experimental/__stf/stream/stream_ctx.cuh>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
using namespace cuda::experimental::stf;
|
||||
|
||||
__global__ void axpy(double a, slice<const double> x, slice<double> y)
|
||||
{
|
||||
int tid = blockIdx.x * blockDim.x + threadIdx.x;
|
||||
int nthreads = gridDim.x * blockDim.x;
|
||||
|
||||
for (int i = tid; i < x.size(); i += nthreads)
|
||||
{
|
||||
y(i) += a * x(i);
|
||||
}
|
||||
}
|
||||
|
||||
double X0(size_t i)
|
||||
{
|
||||
return sin((double) i);
|
||||
}
|
||||
|
||||
double Y0(size_t i)
|
||||
{
|
||||
return cos((double) i);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
// Verify whether this device can access memory concurrently from CPU and GPU.
|
||||
int dev;
|
||||
cuda_safe_call(cudaGetDevice(&dev));
|
||||
assert(dev >= 0);
|
||||
cudaDeviceProp prop;
|
||||
cuda_safe_call(cudaGetDeviceProperties(&prop, dev));
|
||||
if (!prop.concurrentManagedAccess)
|
||||
{
|
||||
fprintf(stderr, "Concurrent CPU/GPU access not supported, skipping test.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
stream_ctx ctx;
|
||||
const size_t N = 16;
|
||||
double Y[N];
|
||||
|
||||
double* X;
|
||||
cuda_safe_call(cudaMallocManaged(&X, N * sizeof(double)));
|
||||
|
||||
for (size_t i = 0; i < N; i++)
|
||||
{
|
||||
X[i] = X0(i);
|
||||
Y[i] = Y0(i);
|
||||
}
|
||||
|
||||
double alpha = 3.14;
|
||||
|
||||
auto lX = ctx.logical_data(make_slice(X, N), data_place::managed());
|
||||
auto lY = ctx.logical_data(Y);
|
||||
|
||||
/* Compute Y = Y + alpha X, but leave X in managed memory */
|
||||
ctx.task(lX.read(data_place::managed()), lY.rw())->*[&](cudaStream_t s, auto dX, auto dY) {
|
||||
axpy<<<16, 128, 0, s>>>(alpha, dX, dY);
|
||||
};
|
||||
|
||||
ctx.finalize();
|
||||
|
||||
for (size_t i = 0; i < N; i++)
|
||||
{
|
||||
assert(fabs(Y[i] - (Y0(i) + alpha * X0(i))) < 0.0001);
|
||||
assert(fabs(X[i] - X0(i)) < 0.0001);
|
||||
}
|
||||
}
|
||||
@@ -1,77 +0,0 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of CUDASTF in CUDA C++ Core Libraries,
|
||||
// under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
// SPDX-FileCopyrightText: Copyright (c) 2022-2024 NVIDIA CORPORATION & AFFILIATES.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include <cuda/experimental/__stf/stream/stream_ctx.cuh>
|
||||
|
||||
using namespace cuda::experimental::stf;
|
||||
|
||||
template <typename T>
|
||||
__global__ void axpy(int n, T a, const T* x, T* y)
|
||||
{
|
||||
int tid = blockIdx.x * blockDim.x + threadIdx.x;
|
||||
int nthreads = gridDim.x * blockDim.x;
|
||||
|
||||
for (int ind = tid; ind < n; ind += nthreads)
|
||||
{
|
||||
y[ind] += a * x[ind];
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
int ndevs;
|
||||
cuda_safe_call(cudaGetDeviceCount(&ndevs));
|
||||
|
||||
cuda_safe_call(cudaSetDevice(0));
|
||||
|
||||
if (ndevs < 2)
|
||||
{
|
||||
fprintf(stderr, "Skipping test that needs at last 2 devices.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
stream_ctx ctx;
|
||||
|
||||
const double alpha = 2.0;
|
||||
const int n = 12;
|
||||
|
||||
double X[n], Y[n];
|
||||
|
||||
for (int ind = 0; ind < n; ind++)
|
||||
{
|
||||
X[ind] = 1.0 * ind;
|
||||
Y[ind] = 2.0 * ind - 3.0;
|
||||
}
|
||||
|
||||
auto handle_X = ctx.logical_data(X);
|
||||
auto handle_Y = ctx.logical_data(Y);
|
||||
|
||||
/* Compute Y = Y + alpha X, but leave X on the host and access it with mapped memory */
|
||||
ctx.task(exec_place::device(1), handle_X.read(), handle_Y.rw())->*[&](cudaStream_t stream, auto X, auto Y) {
|
||||
axpy<<<16, 128, 0, stream>>>(n, alpha, X.data_handle(), Y.data_handle());
|
||||
};
|
||||
|
||||
// Access Ask to use X, Y and Z on the host
|
||||
ctx.task(exec_place::host(), handle_X.read(), handle_Y.read())->*[&](cudaStream_t stream, auto X, auto Y) {
|
||||
cuda_safe_call(cudaStreamSynchronize(stream));
|
||||
|
||||
for (int ind = 0; ind < n; ind++)
|
||||
{
|
||||
// X unchanged
|
||||
EXPECT(fabs(X(ind) - 1.0 * ind) < 0.00001);
|
||||
// Y = Y + alpha X
|
||||
EXPECT(fabs(Y(ind) - (-3.0 + ind * (2.0 + alpha))) < 0.00001);
|
||||
}
|
||||
};
|
||||
|
||||
ctx.finalize();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of CUDASTF in CUDA C++ Core Libraries,
|
||||
// under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
// SPDX-FileCopyrightText: Copyright (c) 2022-2024 NVIDIA CORPORATION & AFFILIATES.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include <cuda/experimental/__places/place_partition.cuh>
|
||||
#include <cuda/experimental/__stf/internal/stf_places_partition_into_stf.cuh>
|
||||
#include <cuda/experimental/stf.cuh>
|
||||
|
||||
using namespace cuda::experimental::stf;
|
||||
|
||||
void print_partition(async_resources_handle& handle, exec_place place, place_partition_scope scope)
|
||||
{
|
||||
fprintf(stderr, "-----------\n");
|
||||
fprintf(
|
||||
stderr, "PARTITION %s (scope: %s):\n", place.to_string().c_str(), place_partition_scope_to_string(scope).c_str());
|
||||
for (auto sub_place : place_partition(place, handle, scope))
|
||||
{
|
||||
fprintf(stderr, "[%s] subplace: %s\n", place.to_string().c_str(), sub_place.to_string().c_str());
|
||||
}
|
||||
|
||||
fprintf(stderr, "-----------\n");
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
#if _CCCL_CTK_BELOW(12, 4)
|
||||
fprintf(stderr, "Green contexts are not supported by this version of CUDA: skipping test.\n");
|
||||
return 0;
|
||||
#else // ^^^ _CCCL_CTK_BELOW(12, 4) ^^^ / vvv _CCCL_CTK_AT_LEAST(12, 4) vvv
|
||||
async_resources_handle handle;
|
||||
|
||||
print_partition(handle, exec_place::all_devices(), place_partition_scope::cuda_device);
|
||||
|
||||
print_partition(handle, exec_place::all_devices(), place_partition_scope::cuda_stream);
|
||||
|
||||
print_partition(handle, exec_place::current_device(), place_partition_scope::cuda_stream);
|
||||
|
||||
print_partition(handle, exec_place::current_device(), place_partition_scope::green_context);
|
||||
print_partition(handle, exec_place::current_device(), place_partition_scope::green_context);
|
||||
|
||||
print_partition(handle, exec_place::repeat(exec_place::current_device(), 4), place_partition_scope::green_context);
|
||||
|
||||
print_partition(handle, exec_place::current_device(), place_partition_scope::cuda_device);
|
||||
|
||||
print_partition(handle, exec_place::repeat(exec_place::current_device(), 4), place_partition_scope::cuda_stream);
|
||||
#endif // ^^^ _CCCL_CTK_AT_LEAST(12, 4) ^^^
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of CUDASTF in CUDA C++ Core Libraries,
|
||||
// under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
// SPDX-FileCopyrightText: Copyright (c) 2022-2024 NVIDIA CORPORATION & AFFILIATES.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include <cuda/experimental/stf.cuh>
|
||||
|
||||
using namespace cuda::experimental::stf;
|
||||
|
||||
void rec_func(exec_place places)
|
||||
{
|
||||
if (places.size() == 1)
|
||||
{
|
||||
// places->print("SINGLE");
|
||||
}
|
||||
else
|
||||
{
|
||||
// places->print("REC");
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
// Take every other places from the grid
|
||||
auto half_places = partition_cyclic(places, dim4(2), pos4(i));
|
||||
rec_func(half_places);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
auto places = exec_place::all_devices();
|
||||
// places->print("ALL");
|
||||
|
||||
rec_func(places);
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user