Skip to content
Open
Show file tree
Hide file tree
Changes from 3 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
6 changes: 4 additions & 2 deletions cpp/bench/common/ml_benchmark.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

#include <cuml/common/logger.hpp>
#include <cuml/common/utils.hpp>
#include <cuml/common/checked_arithmetic.hpp>

#include <raft/util/cudart_utils.hpp>

Expand Down Expand Up @@ -158,7 +159,7 @@ class Fixture : public ::benchmark::Fixture {
template <typename T>
void alloc(T*& ptr, size_t len, bool init = false)
{
auto nBytes = len * sizeof(T);
auto nBytes = ML::checked_mul<size_t>(len, sizeof(T));
auto d_alloc = rmm::mr::get_current_device_resource_ref();
ptr = (T*)d_alloc.allocate(stream, nBytes);
if (init) { RAFT_CUDA_TRY(cudaMemsetAsync(ptr, 0, nBytes, stream)); }
Expand All @@ -168,7 +169,8 @@ class Fixture : public ::benchmark::Fixture {
void dealloc(T* ptr, size_t len)
{
auto d_alloc = rmm::mr::get_current_device_resource_ref();
d_alloc.deallocate(stream, ptr, len * sizeof(T));
auto nBytes = ML::checked_mul<size_t>(len, sizeof(T));
d_alloc.deallocate(stream, ptr, nBytes);
}

cudaStream_t stream = 0;
Expand Down
75 changes: 47 additions & 28 deletions cpp/include/cuml/prims/opg/matrix/data.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,39 +5,58 @@
* SPDX-License-Identifier: Apache-2.0
*/

#include <cstddef>

#include <cuml/common/checked_arithmetic.hpp>
#include <cuml/common/export.hpp>

namespace CUML_EXPORT MLCommon {
namespace Matrix {

/**
* @brief This is a *helper* wrapper around the multi-gpu data blocks owned
* by a worker. It's design is NOT final. Its so written this way to get
* something concrete in a short span of time.
* @todo add support for custom allocators
*/
template <typename Type>
struct Data {
Data() : ptr(nullptr), totalSize(0) {}
Data(Type* _ptr, size_t _n_elements) : ptr(_ptr), totalSize(_n_elements * sizeof(Type)) {}

/**
* actual data block. This is just a linearly laid out buffer of all blocks
* owned by this worker
*/
Type* ptr = nullptr;

/**
* total size (in bytes) of this buffer. In future, this will be passed
* to the dealloc function underneath
*/
size_t totalSize = (size_t)0;

/**
* Return the number of elements of Type in ptr.
*/
size_t numElements() const { return totalSize / sizeof(Type); }
};
/**
* @brief This is a *helper* wrapper around the multi-gpu data blocks owned
* by a worker. It's design is NOT final. Its so written this way to get
* something concrete in a short span of time.
* @todo add support for custom allocators
*/
template <typename Type>
struct Data {
Data() : ptr(nullptr), nElements(0), totalSize(0) {}
Data(Type* _ptr, size_t _n_elements)
: ptr(_ptr),
nElements(_n_elements),
totalSize(ML::checked_mul<size_t>(_n_elements, sizeof(Type)))
{
}

void setNumElements(size_t _n_elements)
{
nElements = _n_elements;
totalSize = ML::checked_mul<size_t>(_n_elements, sizeof(Type));
}

/**
* actual data block. This is just a linearly laid out buffer of all blocks
* owned by this worker
*/
Type* ptr = nullptr;

/**
* number of elements in this buffer.
*/
size_t nElements = 0;

/**
* total size (in bytes) of this buffer. In future, this will be passed
* to the dealloc function underneath
*/
size_t totalSize = (size_t)0;

/**
* Return the number of elements of Type in ptr.
*/
size_t numElements() const { return nElements; }
};

typedef Data<float> floatData_t;
typedef Data<double> doubleData_t;
Expand Down
4 changes: 2 additions & 2 deletions cpp/src/glm/ridge_mg.cu
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ void ridgeSolve(const raft::handle_t& handle,
raft::make_device_vector_view<const T, std::size_t>(S, UDesc.N));

MLCommon::Matrix::Data<T> S_nnz_data;
S_nnz_data.totalSize = UDesc.N;
S_nnz_data.setNumElements(UDesc.N);
S_nnz_data.ptr = S_nnz;
MLCommon::LinAlg::opg::mv_aTb(handle, S_nnz_data, U, UDesc, b, streams, n_streams);

Expand Down Expand Up @@ -125,7 +125,7 @@ void ridgeEig(raft::handle_t& handle,

for (std::size_t i = 0; i < partsToRanks.size(); i++) {
MLCommon::Matrix::Data<T> d;
d.totalSize = partsToRanks[i]->size;
d.setNumElements(partsToRanks[i]->size);
d.ptr = curr_ptr;
curr_ptr = curr_ptr + (partsToRanks[i]->size * ADesc.N);
U_temp.push_back(d);
Expand Down
8 changes: 4 additions & 4 deletions cpp/src/solver/cd_mg.cu
Original file line number Diff line number Diff line change
Expand Up @@ -116,11 +116,11 @@ int fit_impl(raft::handle_t& handle,

MLCommon::Matrix::Data<T>* rs_data = new MLCommon::Matrix::Data<T>();
rs_data->ptr = rs;
rs_data->totalSize = partsToRanks[i]->size;
rs_data->setNumElements(partsToRanks[i]->size);
residual_temp.push_back(rs_data);

MLCommon::Matrix::Data<T>* temp_data = new MLCommon::Matrix::Data<T>();
temp_data->totalSize = partsToRanks[i]->size;
temp_data->setNumElements(partsToRanks[i]->size);
input_data_temp.push_back(temp_data);

rs += partsToRanks[i]->size;
Expand Down Expand Up @@ -156,7 +156,7 @@ int fit_impl(raft::handle_t& handle,
input_col_loc = input_data[k]->ptr + (ci * partsToRanks[k]->size);

input_data_temp[k]->ptr = input_col_loc;
input_data_temp[k]->totalSize = partsToRanks[k]->size;
input_data_temp[k]->setNumElements(partsToRanks[k]->size);

raft::linalg::multiplyScalar(
pred_loc, input_col_loc, h_coef[ci], partsToRanks[k]->size, streams[k % n_streams]);
Expand All @@ -173,7 +173,7 @@ int fit_impl(raft::handle_t& handle,
}

coef_loc_data.ptr = coef_loc;
coef_loc_data.totalSize = size_t(1);
coef_loc_data.setNumElements(size_t(1));
MLCommon::LinAlg::opg::mv_aTb(
handle, coef_loc_data, input_data_temp, input_desc_temp, residual_temp, streams, n_streams);

Expand Down
4 changes: 2 additions & 2 deletions cpp/src_prims/opg/linalg/lstsq.cu
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ void lstsqEig_impl(const raft::handle_t& handle,

for (size_t i = 0; i < partsToRanks.size(); i++) {
Matrix::Data<T> d;
d.totalSize = partsToRanks[i]->size;
d.setNumElements(partsToRanks[i]->size);
d.ptr = curr_ptr;
curr_ptr = curr_ptr + (partsToRanks[i]->size * ADesc.N);
U_temp.push_back(d);
Expand All @@ -66,7 +66,7 @@ void lstsqEig_impl(const raft::handle_t& handle,

Matrix::Data<T> w_out;
w_out.ptr = tmp_vector.data();
w_out.totalSize = ADesc.N;
w_out.setNumElements(ADesc.N);

mv_aTb(handle, w_out, U, ADesc, b, streams, n_streams);

Expand Down
2 changes: 2 additions & 0 deletions cpp/tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,8 @@ if(BUILD_PRIMS_TESTS)
ConfigureTest(PREFIX PRIMS NAME LINEARREG_TEST prims/linearReg.cu)
ConfigureTest(PREFIX PRIMS NAME LOG_TEST prims/log.cu)
ConfigureTest(PREFIX PRIMS NAME LOGISTICREG_TEST prims/logisticReg.cu)
ConfigureTest(PREFIX PRIMS NAME ML_BENCHMARK_TEST prims/ml_benchmark.cpp ML_INCLUDE)
ConfigureTest(PREFIX PRIMS NAME MATRIX_DATA_TEST prims/matrix_data.cpp ML_INCLUDE)
ConfigureTest(PREFIX PRIMS NAME MAKE_ARIMA_TEST prims/make_arima.cu)
ConfigureTest(PREFIX PRIMS NAME PENALTY_TEST prims/penalty.cu)
ConfigureTest(PREFIX PRIMS NAME SIGMOID_TEST prims/sigmoid.cu)
Expand Down
40 changes: 40 additions & 0 deletions cpp/tests/prims/matrix_data.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* SPDX-FileCopyrightText: Copyright (c) 2026, NVIDIA CORPORATION.
* SPDX-License-Identifier: Apache-2.0
*/

#include <cuml/prims/opg/matrix/data.hpp>

#include <gtest/gtest.h>
#include <raft/core/error.hpp>

#include <cstddef>
#include <limits>

namespace MLCommon {
namespace Matrix {

TEST(MatrixData, ComputesBytesAndElements)
{
float value = 1.0f;
Data<float> data(&value, size_t(4));

EXPECT_EQ(data.numElements(), 4u);
EXPECT_EQ(data.totalSize, data.numElements() * sizeof(float));

data.setNumElements(2);
EXPECT_EQ(data.numElements(), 2u);
EXPECT_EQ(data.totalSize, data.numElements() * sizeof(float));
}

TEST(MatrixData, ThrowsOnElementCountOverflowForByteSize)
{
float* ptr = nullptr;
auto max_elements = std::numeric_limits<size_t>::max() / sizeof(float);

EXPECT_THROW(Data<float> data(ptr, max_elements + 1), raft::exception);
EXPECT_THROW(Data<float>{ptr, size_t(0)}.setNumElements(max_elements + 1), raft::exception);
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated
}

} // namespace Matrix
} // namespace MLCommon
51 changes: 51 additions & 0 deletions cpp/tests/prims/ml_benchmark.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* SPDX-FileCopyrightText: Copyright (c) 2026, NVIDIA CORPORATION.
* SPDX-License-Identifier: Apache-2.0
*/

#include "../bench/common/ml_benchmark.hpp"

#include <raft/core/error.hpp>

#include <gtest/gtest.h>

#include <benchmark/benchmark.h>

#include <cstddef>
#include <limits>

namespace MLCommon {
namespace Bench {

class TestFixture : public Fixture {
public:
TestFixture() : Fixture("MLBenchmarkFixtureTest") {}

void runBenchmark(::benchmark::State&) override {}

template <typename T>
void testAlloc(T*& ptr, size_t len, bool init = false)
{
alloc(ptr, len, init);
}

template <typename T>
void testDealloc(T* ptr, size_t len)
{
dealloc(ptr, len);
}
};

TEST(MlBenchmarkFixtureAllocator, ThrowOnHugeAllocationOrDeallocationLength)
{
TestFixture fixture;

int* ptr = nullptr;
auto const len = std::numeric_limits<size_t>::max() / sizeof(int) + 1;

EXPECT_THROW(fixture.testAlloc(ptr, len), raft::exception);
EXPECT_THROW(fixture.testDealloc(ptr, len), raft::exception);
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.

} // namespace Bench
} // namespace MLCommon
Loading