10#include <uni20/config.hpp>
16#if UNI20_BACKEND_CUBLAS
30namespace partitioned_buffer_detail
33template <std::
size_t OperandCount, std::
size_t MaximumRank>
35 -> detail::cuda_reference::LoweredStridedElementwisePlan<OperandCount, MaximumRank>
37 using namespace detail::cuda_reference;
38 LoweredStridedElementwisePlan<OperandCount, MaximumRank> result;
39 if (size <=
static_cast<std::size_t
>(std::numeric_limits<std::int32_t>::max()))
41 result.index_kind = ElementwiseIndexKind::index_32;
42 result.plan_32.element_count =
static_cast<std::uint32_t
>(size);
43 result.plan_32.compact_rank = size == 0 ? 0 : 1;
46 result.plan_32.extents[0] =
static_cast<std::uint32_t
>(size);
47 result.plan_32.strides[0].fill(1);
52 result.index_kind = ElementwiseIndexKind::index_64;
53 result.plan_64.element_count =
static_cast<std::uint64_t
>(size);
54 result.plan_64.compact_rank = size == 0 ? 0 : 1;
57 result.plan_64.extents[0] =
static_cast<std::uint64_t
>(size);
58 result.plan_64.strides[0].fill(1);
67 (completion.
release(accesses), ...);
73template <
class Scalar>
77template <
class Scalar,
class Factor>
79 detail::cuda_reference::supports_elementwise_scale<Scalar, std::remove_cvref_t<Factor>>;
82template <
class Scalar>
83 requires cuda_partitioned_fill_scalar<Scalar>
86 if (output.
size() == 0)
return;
87 using namespace detail::cuda_reference;
91 partitioned_buffer_detail::make_contiguous_plan<1, elementwise_arithmetic_maximum_rank>(output.
size());
93 plan.visit([&](
auto const& concrete) {
94 enqueue_elementwise_fill(access.data(),
Scalar{}, concrete, stream.native_handle(), stream.device());
100template <
class Scalar,
class Factor>
101 requires cuda_partitioned_scale_scalars<Scalar, Factor>
104 if (output.
size() == 0)
return;
105 using namespace detail::cuda_reference;
109 partitioned_buffer_detail::make_contiguous_plan<1, elementwise_arithmetic_maximum_rank>(output.
size());
111 plan.visit([&](
auto const& concrete) {
112 enqueue_elementwise_inplace_scale(access.data(), factor, concrete, stream.native_handle(), stream.device());
118template <
class Scalar,
class Factor>
119 requires cuda_partitioned_scale_scalars<Scalar, Factor>
124 if (output.
size() == 0)
return;
126 using namespace detail::cuda_reference;
130 auto const plan = partitioned_buffer_detail::make_contiguous_plan<2, elementwise_scale_maximum_rank>(output.
size());
132 plan.visit([&](
auto const& concrete) {
133 enqueue_elementwise_scale(output_access.data(), input_access.data(), factor, concrete, stream.native_handle(),
140template <
class Scalar,
class Factor>
141 requires cuda_partitioned_scale_scalars<Scalar, Factor>
146 if (output.
size() == 0)
return;
148 using namespace detail::cuda_reference;
153 partitioned_buffer_detail::make_contiguous_plan<2, elementwise_arithmetic_maximum_rank>(output.
size());
155 plan.visit([&](
auto const& concrete) {
156 enqueue_elementwise_add_scaled(output_access.data(), input_access.data(), factor, concrete, stream.native_handle(),
162#if UNI20_BACKEND_CUBLAS
165[[nodiscard]]
constexpr auto cuda_partitioned_reduction_size_supported(std::size_t size)
noexcept ->
bool
167 return size <= static_cast<std::size_t>(std::numeric_limits<int>::max());
171template <uni20::cublas::CublasLevelOneScalar Scalar>
172[[nodiscard]]
auto cuda_partitioned_inner_product_host(cuda::PartitionedCudaBuffer<Scalar>
const& lhs,
173 cuda::PartitionedCudaBuffer<Scalar>
const& rhs) -> Scalar
176 CHECK(cuda_partitioned_reduction_size_supported(lhs.size()), lhs.size());
177 if (lhs.size() == 0)
return Scalar{};
178 CHECK_EQUAL(lhs.device().ordinal(), rhs.device().ordinal());
180 auto lhs_access = lhs.read_synchronized_with(execution.stream());
181 auto rhs_access = rhs.read_synchronized_with(execution.stream());
182 auto result =
uni20::cublas::dotc(execution,
static_cast<int>(lhs.size()), lhs_access.data(), rhs_access.data());
183 lhs_access.release_after_synchronization();
184 rhs_access.release_after_synchronization();
189template <uni20::cublas::CublasLevelOneScalar Scalar>
190[[nodiscard]]
auto cuda_partitioned_norm_host(cuda::PartitionedCudaBuffer<Scalar>
const& input) -> make_real_t<Scalar>
192 CHECK(cuda_partitioned_reduction_size_supported(input.size()), input.size());
193 if (input.size() == 0)
return make_real_t<Scalar>{};
195 auto access = input.read_synchronized_with(execution.stream());
196 auto result =
uni20::cublas::nrm2(execution,
static_cast<int>(input.size()), access.data());
197 access.release_after_synchronization();
Typed CUDA device buffers and scoped stream access guards.
ExecutionLease acquire()
Block until a handle and then an idle stream are available.
Definition cublas/execution.cpp:203
One operation-tail completion shared by multiple CUDA buffer accesses.
Definition buffer.hpp:1160
void release(Access &access) const noexcept
Release one participating access through the shared completion.
Definition buffer.hpp:1181
StreamPool & streams() noexcept
Return the device's actually-idle stream pool.
Definition runtime.hpp:244
constexpr int ordinal() const noexcept
Return this device's CUDA runtime ordinal.
Definition device.hpp:123
One CUDA allocation partitioned into independent logical buffers.
Definition buffer.hpp:709
auto read_synchronized_with(Stream const &stream) const -> PartitionedReadAccess< T >
Acquire read access to the complete contiguous allocation.
Definition buffer.hpp:1195
Device device() const
Return the CUDA device containing the physical allocation.
Definition buffer.hpp:755
std::size_t size() const noexcept
Return the total physical allocation size in elements.
Definition buffer.hpp:736
DeviceResources & resources() const
Return the device resources shared by every child buffer.
Definition buffer.hpp:748
auto write_synchronized_with(Stream const &stream) -> PartitionedWriteAccess< T >
Acquire write access to the complete contiguous allocation.
Definition buffer.hpp:1202
Temporarily select one CUDA device and restore the previous device on destruction.
Definition runtime.hpp:44
Stream acquire()
Block until one actually idle stream can be leased.
Definition runtime.cpp:594
Reference-counted lease of one CUDA stream-pool slot.
Definition runtime.hpp:65
Concept for numeric scalar types (integer, real, or complex).
Definition scalar_concepts.hpp:81
cuBLAS handle slots and dynamically paired stream execution leases.
Compiled CUDA entry points for named stateless arithmetic transforms.
Typed launch boundary for CUDA accessor-respecting element copies.
CUDA lowering for compact affine elementwise iteration plans.
Compiled CUDA entry points for elementwise scaling.
Checked cuBLAS dot-product and Euclidean-norm wrappers.
auto nrm2(ExecutionLease &execution, int size, Scalar const *input) -> uni20::make_real_t< Scalar >
Compute a Euclidean norm and return a host real scalar.
Definition level1.hpp:117
auto dotc(ExecutionLease &execution, int size, Scalar const *lhs, Scalar const *rhs) -> Scalar
Compute the conjugate-linear dot product and return a host scalar.
Definition level1.hpp:62
ExecutionPool & execution_pool(cuda::DeviceResources &resources)
Return the lazily constructed cuBLAS execution pool for one CUDA device.
Definition cublas/execution.cpp:215
void publish(cuda::Stream const &stream, Accesses &... accesses)
Definition partitioned_buffer_linear.hpp:64
auto make_contiguous_plan(std::size_t size) -> detail::cuda_reference::LoweredStridedElementwisePlan< OperandCount, MaximumRank >
Definition partitioned_buffer_linear.hpp:34
Definition linalg/async.hpp:28
void cuda_partitioned_axpy(cuda::PartitionedCudaBuffer< Scalar > &output, Factor factor, cuda::PartitionedCudaBuffer< Scalar > const &input)
Add a scaled partitioned CUDA allocation to another in place.
Definition partitioned_buffer_linear.hpp:142
void cuda_partitioned_set_zero(cuda::PartitionedCudaBuffer< Scalar > &output)
Set a complete partitioned CUDA allocation to numerical zero.
Definition partitioned_buffer_linear.hpp:84
void cuda_partitioned_scale(cuda::PartitionedCudaBuffer< Scalar > &output, Factor factor)
Scale a complete partitioned CUDA allocation in place.
Definition partitioned_buffer_linear.hpp:102
void cuda_partitioned_assign_scale(cuda::PartitionedCudaBuffer< Scalar > &output, Factor factor, cuda::PartitionedCudaBuffer< Scalar > const &input)
Overwrite one partitioned CUDA allocation with a scaled peer allocation.
Definition partitioned_buffer_linear.hpp:120
constexpr bool cuda_partitioned_fill_scalar
Whether allocation-wide CUDA fill operations support Scalar.
Definition partitioned_buffer_linear.hpp:74
constexpr bool cuda_partitioned_scale_scalars
Whether allocation-wide CUDA scale operations support this scalar pair.
Definition partitioned_buffer_linear.hpp:78
#define CHECK(cond,...)
Definition trace.hpp:299
#define CHECK_EQUAL(a, b,...)
Definition trace.hpp:309