diff --git a/cpp/daal/src/algorithms/low_order_moments/low_order_moments_csr_fast_online_fpt_cpu.cpp b/cpp/daal/src/algorithms/low_order_moments/low_order_moments_csr_fast_online_fpt_cpu.cpp index bba54d959d4..e9646fb40fd 100644 --- a/cpp/daal/src/algorithms/low_order_moments/low_order_moments_csr_fast_online_fpt_cpu.cpp +++ b/cpp/daal/src/algorithms/low_order_moments/low_order_moments_csr_fast_online_fpt_cpu.cpp @@ -37,7 +37,7 @@ namespace internal { template class OnlineContainer; -template class LowOrderMomentsOnlineKernel; +template class DAAL_EXPORT LowOrderMomentsOnlineKernel; } // namespace internal } // namespace low_order_moments } // namespace algorithms diff --git a/cpp/oneapi/dal/algo/basic_statistics/backend/cpu/finalize_compute_kernel_dense.cpp b/cpp/oneapi/dal/algo/basic_statistics/backend/cpu/finalize_compute_kernel_dense.cpp index caa343762d2..953dd10e472 100644 --- a/cpp/oneapi/dal/algo/basic_statistics/backend/cpu/finalize_compute_kernel_dense.cpp +++ b/cpp/oneapi/dal/algo/basic_statistics/backend/cpu/finalize_compute_kernel_dense.cpp @@ -31,7 +31,6 @@ namespace oneapi::dal::basic_statistics::backend { using dal::backend::context_cpu; -using method_t = method::dense; using task_t = task::compute; using input_t = compute_input; using result_t = compute_result; @@ -41,11 +40,23 @@ namespace daal_lom = daal::algorithms::low_order_moments; namespace interop = dal::backend::interop; namespace bk = dal::backend; -template +template +using daal_method_constant = std::integral_constant; + +template +struct to_daal_method; + +template <> +struct to_daal_method : daal_method_constant {}; + +template <> +struct to_daal_method : daal_method_constant {}; + +template using daal_lom_online_kernel_t = - daal_lom::internal::LowOrderMomentsOnlineKernel; + daal_lom::internal::LowOrderMomentsOnlineKernel::value, Cpu>; -template +template static compute_result call_daal_kernel_finalize_compute( const context_cpu& ctx, const descriptor_t& desc, @@ -80,19 +91,22 @@ static compute_result call_daal_kernel_finalize_compute( auto daal_stdev = interop::allocate_daal_homogen_table(1, column_count); auto daal_variation = interop::allocate_daal_homogen_table(1, column_count); if (result_ids == daal_lom::estimatesMeanVariance || result_ids == daal_lom::estimatesAll) { - interop::status_to_exception( - interop::call_daal_kernel_finalize_compute( - ctx, - daal_partial_obs.get(), - daal_partial_sums.get(), - daal_partial_sum_squares.get(), - daal_partial_sum_squares_centered.get(), - daal_means.get(), - daal_rawt.get(), - daal_variance.get(), - daal_stdev.get(), - daal_variation.get(), - &daal_parameter)); + interop::status_to_exception(dal::backend::dispatch_by_cpu(ctx, [&](auto cpu) { + return daal_lom_online_kernel_t< + Float, + oneapi::dal::backend::interop::to_daal_cpu_type::value, + Method>() + .finalizeCompute(daal_partial_obs.get(), + daal_partial_sums.get(), + daal_partial_sum_squares.get(), + daal_partial_sum_squares_centered.get(), + daal_means.get(), + daal_rawt.get(), + daal_variance.get(), + daal_stdev.get(), + daal_variation.get(), + &daal_parameter); + })); } compute_result res; res.set_result_options(desc.get_result_options()); @@ -132,24 +146,26 @@ static compute_result call_daal_kernel_finalize_compute( return res; } -template +template static compute_result finalize_compute(const context_cpu& ctx, const descriptor_t& desc, const partial_compute_result& input) { - return call_daal_kernel_finalize_compute(ctx, desc, input); + return call_daal_kernel_finalize_compute(ctx, desc, input); } -template -struct finalize_compute_kernel_cpu { +template +struct finalize_compute_kernel_cpu { compute_result operator()( const context_cpu& ctx, const descriptor_t& desc, const partial_compute_result& input) const { - return finalize_compute(ctx, desc, input); + return finalize_compute(ctx, desc, input); } }; -template struct finalize_compute_kernel_cpu; -template struct finalize_compute_kernel_cpu; +template struct finalize_compute_kernel_cpu; +template struct finalize_compute_kernel_cpu; +template struct finalize_compute_kernel_cpu; +template struct finalize_compute_kernel_cpu; } // namespace oneapi::dal::basic_statistics::backend diff --git a/cpp/oneapi/dal/algo/basic_statistics/backend/cpu/partial_compute_kernel_dense.cpp b/cpp/oneapi/dal/algo/basic_statistics/backend/cpu/partial_compute_kernel_dense.cpp index 06a6463647e..2e50d58d39f 100644 --- a/cpp/oneapi/dal/algo/basic_statistics/backend/cpu/partial_compute_kernel_dense.cpp +++ b/cpp/oneapi/dal/algo/basic_statistics/backend/cpu/partial_compute_kernel_dense.cpp @@ -32,7 +32,6 @@ namespace oneapi::dal::basic_statistics::backend { using dal::backend::context_cpu; -using method_t = method::dense; using task_t = task::compute; using input_t = partial_compute_input; using result_t = partial_compute_result; @@ -41,8 +40,24 @@ using descriptor_t = detail::descriptor_base; namespace daal_lom = daal::algorithms::low_order_moments; namespace interop = dal::backend::interop; -template +template +using daal_method_constant = std::integral_constant; + +template +struct to_daal_method; + +template <> +struct to_daal_method : daal_method_constant {}; + +template <> +struct to_daal_method : daal_method_constant {}; + +template using daal_lom_online_kernel_t = + daal_lom::internal::LowOrderMomentsOnlineKernel::value, Cpu>; + +template +using daal_lom_online_dense_kernel_t = daal_lom::internal::LowOrderMomentsOnlineKernel; template @@ -146,11 +161,11 @@ result_t call_daal_kernel_with_weights(const context_cpu& ctx, } { interop::status_to_exception( - interop::call_daal_kernel(ctx, - daal_data.get(), - &daal_partial, - &daal_parameter, - is_online)); + interop::call_daal_kernel(ctx, + daal_data.get(), + &daal_partial, + &daal_parameter, + is_online)); } auto result = get_partial_result(daal_partial, desc); @@ -159,18 +174,18 @@ result_t call_daal_kernel_with_weights(const context_cpu& ctx, else { { interop::status_to_exception( - interop::call_daal_kernel(ctx, - daal_data.get(), - &daal_partial, - &daal_parameter, - is_online)); + interop::call_daal_kernel(ctx, + daal_data.get(), + &daal_partial, + &daal_parameter, + is_online)); } auto result = get_partial_result(daal_partial, desc); return result; } } -template +template result_t call_daal_kernel_without_weights(const context_cpu& ctx, const descriptor_t& desc, const partial_compute_input& input) { @@ -223,52 +238,56 @@ result_t call_daal_kernel_without_weights(const context_cpu& ctx, daal_partial.set(daal_lom::PartialResultId::partialSumSquares, daal_partial_sum_squares); } - interop::status_to_exception( - interop::call_daal_kernel(ctx, - daal_data.get(), - &daal_partial, - &daal_parameter, - is_online)); + interop::status_to_exception(dal::backend::dispatch_by_cpu(ctx, [&](auto cpu) { + return daal_lom_online_kernel_t< + Float, + oneapi::dal::backend::interop::to_daal_cpu_type::value, + Method>() + .compute(daal_data.get(), &daal_partial, &daal_parameter, is_online); + })); auto result = get_partial_result(daal_partial, desc); return result; } else { { - interop::status_to_exception( - interop::call_daal_kernel(ctx, - daal_data.get(), - &daal_partial, - &daal_parameter, - is_online)); + interop::status_to_exception(dal::backend::dispatch_by_cpu(ctx, [&](auto cpu) { + return daal_lom_online_kernel_t< + Float, + oneapi::dal::backend::interop::to_daal_cpu_type::value, + Method>() + .compute(daal_data.get(), &daal_partial, &daal_parameter, is_online); + })); } auto result = get_partial_result(daal_partial, desc); return result; } } -template +template static partial_compute_result partial_compute(const context_cpu& ctx, const descriptor_t& desc, const partial_compute_input& input) { if (input.get_weights().has_data()) { - return call_daal_kernel_with_weights(ctx, desc, input); + return call_daal_kernel_with_weights(ctx, desc, input); } else { - return call_daal_kernel_without_weights(ctx, desc, input); + return call_daal_kernel_without_weights(ctx, desc, input); } } -template -struct partial_compute_kernel_cpu { +template +struct partial_compute_kernel_cpu { partial_compute_result operator()( const context_cpu& ctx, const descriptor_t& desc, const partial_compute_input& input) const { - return partial_compute(ctx, desc, input); + return partial_compute(ctx, desc, input); } }; -template struct partial_compute_kernel_cpu; -template struct partial_compute_kernel_cpu; +template struct partial_compute_kernel_cpu; +template struct partial_compute_kernel_cpu; +template struct partial_compute_kernel_cpu; +template struct partial_compute_kernel_cpu; } // namespace oneapi::dal::basic_statistics::backend diff --git a/cpp/oneapi/dal/algo/basic_statistics/backend/gpu/finalize_compute_kernel_sparse_dpc.cpp b/cpp/oneapi/dal/algo/basic_statistics/backend/gpu/finalize_compute_kernel_sparse_dpc.cpp new file mode 100644 index 00000000000..0c54f09bb35 --- /dev/null +++ b/cpp/oneapi/dal/algo/basic_statistics/backend/gpu/finalize_compute_kernel_sparse_dpc.cpp @@ -0,0 +1,41 @@ +/******************************************************************************* +* Copyright contributors to the oneDAL project +* +* 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. +*******************************************************************************/ + +#include "oneapi/dal/algo/basic_statistics/backend/gpu/finalize_compute_kernel.hpp" +#include "oneapi/dal/exceptions.hpp" + +namespace oneapi::dal::basic_statistics::backend { + +using dal::backend::context_gpu; +using method_t = method::sparse; +using task_t = task::compute; +using input_t = partial_compute_result; +using result_t = compute_result; +using descriptor_t = detail::descriptor_base; + +template +struct finalize_compute_kernel_gpu { + result_t operator()(const context_gpu& ctx, + const descriptor_t& desc, + const input_t& input) const { + throw unimplemented(dal::detail::error_messages::method_not_implemented()); + } +}; + +template struct finalize_compute_kernel_gpu; +template struct finalize_compute_kernel_gpu; + +} // namespace oneapi::dal::basic_statistics::backend diff --git a/cpp/oneapi/dal/algo/basic_statistics/backend/gpu/partial_compute_kernel_sparse_dpc.cpp b/cpp/oneapi/dal/algo/basic_statistics/backend/gpu/partial_compute_kernel_sparse_dpc.cpp new file mode 100644 index 00000000000..01ee048b3ac --- /dev/null +++ b/cpp/oneapi/dal/algo/basic_statistics/backend/gpu/partial_compute_kernel_sparse_dpc.cpp @@ -0,0 +1,41 @@ +/******************************************************************************* +* Copyright contributors to the oneDAL project +* +* 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. +*******************************************************************************/ + +#include "oneapi/dal/algo/basic_statistics/backend/gpu/partial_compute_kernel.hpp" +#include "oneapi/dal/exceptions.hpp" + +namespace oneapi::dal::basic_statistics::backend { + +using dal::backend::context_gpu; +using method_t = method::sparse; +using task_t = task::compute; +using input_t = partial_compute_input; +using result_t = partial_compute_result; +using descriptor_t = detail::descriptor_base; + +template +struct partial_compute_kernel_gpu { + result_t operator()(const context_gpu& ctx, + const descriptor_t& desc, + const input_t& input) const { + throw unimplemented(dal::detail::error_messages::method_not_implemented()); + } +}; + +template struct partial_compute_kernel_gpu; +template struct partial_compute_kernel_gpu; + +} // namespace oneapi::dal::basic_statistics::backend diff --git a/cpp/oneapi/dal/algo/basic_statistics/detail/finalize_compute_ops.cpp b/cpp/oneapi/dal/algo/basic_statistics/detail/finalize_compute_ops.cpp index b5e62340cb4..e3cb9f3bc22 100644 --- a/cpp/oneapi/dal/algo/basic_statistics/detail/finalize_compute_ops.cpp +++ b/cpp/oneapi/dal/algo/basic_statistics/detail/finalize_compute_ops.cpp @@ -38,6 +38,8 @@ struct finalize_compute_ops_dispatcher { INSTANTIATE(float, method::dense, task::compute) INSTANTIATE(double, method::dense, task::compute) +INSTANTIATE(float, method::sparse, task::compute) +INSTANTIATE(double, method::sparse, task::compute) } // namespace v1 } // namespace oneapi::dal::basic_statistics::detail diff --git a/cpp/oneapi/dal/algo/basic_statistics/detail/finalize_compute_ops_dpc.cpp b/cpp/oneapi/dal/algo/basic_statistics/detail/finalize_compute_ops_dpc.cpp index 03b23e77b64..5c23a386bd2 100644 --- a/cpp/oneapi/dal/algo/basic_statistics/detail/finalize_compute_ops_dpc.cpp +++ b/cpp/oneapi/dal/algo/basic_statistics/detail/finalize_compute_ops_dpc.cpp @@ -42,6 +42,8 @@ struct finalize_compute_ops_dispatcher { INSTANTIATE(float, method::dense, task::compute) INSTANTIATE(double, method::dense, task::compute) +INSTANTIATE(float, method::sparse, task::compute) +INSTANTIATE(double, method::sparse, task::compute) } // namespace v1 } // namespace oneapi::dal::basic_statistics::detail diff --git a/cpp/oneapi/dal/algo/basic_statistics/detail/partial_compute_ops.cpp b/cpp/oneapi/dal/algo/basic_statistics/detail/partial_compute_ops.cpp index f8b3ab06dfc..af0545c99b0 100644 --- a/cpp/oneapi/dal/algo/basic_statistics/detail/partial_compute_ops.cpp +++ b/cpp/oneapi/dal/algo/basic_statistics/detail/partial_compute_ops.cpp @@ -37,6 +37,8 @@ struct partial_compute_ops_dispatcher { INSTANTIATE(float, method::dense, task::compute) INSTANTIATE(double, method::dense, task::compute) +INSTANTIATE(float, method::sparse, task::compute) +INSTANTIATE(double, method::sparse, task::compute) } // namespace v1 } // namespace oneapi::dal::basic_statistics::detail diff --git a/cpp/oneapi/dal/algo/basic_statistics/detail/partial_compute_ops_dpc.cpp b/cpp/oneapi/dal/algo/basic_statistics/detail/partial_compute_ops_dpc.cpp index 958c2a8eec4..271b5dba09d 100644 --- a/cpp/oneapi/dal/algo/basic_statistics/detail/partial_compute_ops_dpc.cpp +++ b/cpp/oneapi/dal/algo/basic_statistics/detail/partial_compute_ops_dpc.cpp @@ -40,6 +40,8 @@ struct partial_compute_ops_dispatcher { INSTANTIATE(float, method::dense, task::compute) INSTANTIATE(double, method::dense, task::compute) +INSTANTIATE(float, method::sparse, task::compute) +INSTANTIATE(double, method::sparse, task::compute) } // namespace v1 } // namespace oneapi::dal::basic_statistics::detail diff --git a/cpp/oneapi/dal/algo/basic_statistics/test/fixture.hpp b/cpp/oneapi/dal/algo/basic_statistics/test/fixture.hpp index 0386a9d6188..351426e4dbf 100644 --- a/cpp/oneapi/dal/algo/basic_statistics/test/fixture.hpp +++ b/cpp/oneapi/dal/algo/basic_statistics/test/fixture.hpp @@ -104,6 +104,55 @@ class basic_statistics_test : public te::crtp_algo_fixture { return (data.row_count_ > 100 || data.column_count_ > 100) && policy.is_cpu(); } + std::vector split_csr_by_rows(const csr_table& table, std::int64_t split_count) { + ONEDAL_ASSERT(split_count > 0); + const std::int64_t row_count = table.get_row_count(); + const std::int64_t column_count = table.get_column_count(); + const std::int64_t block_size_regular = row_count / split_count; + const std::int64_t block_size_tail = row_count % split_count; + const auto indexing = table.get_indexing(); + + csr_accessor accessor(table); + std::vector result(split_count); + + std::int64_t row_offset = 0; + for (std::int64_t i = 0; i < split_count; ++i) { + const std::int64_t tail = std::int64_t(i + 1 == split_count) * block_size_tail; + const std::int64_t block_size = block_size_regular + tail; + if (block_size <= 0) { + result[i] = csr_table{}; + row_offset += block_size; + continue; + } + const auto [data_arr, col_arr, row_arr] = + accessor.pull({ row_offset, row_offset + block_size }, indexing); + result[i] = csr_table::wrap(data_arr, col_arr, row_arr, column_count, indexing); + row_offset += block_size; + } + return result; + } + + void csr_online_general_checks(const te::csr_table_builder<>& data, + bs::result_option_id compute_mode, + std::int64_t nBlocks) { + CAPTURE(compute_mode, nBlocks); + const auto bs_desc = + bs::descriptor{}.set_result_options( + compute_mode); + const auto csr_full = data.build_csr_table(this->get_policy()); + const auto dense_full = data.build_dense_table(this->get_policy()); + + const auto blocks = split_csr_by_rows(csr_full, nBlocks); + dal::basic_statistics::partial_compute_result<> partial_result; + for (std::int64_t i = 0; i < nBlocks; ++i) { + partial_result = this->partial_compute(bs_desc, partial_result, blocks[i]); + } + auto compute_result = this->finalize_compute(bs_desc, partial_result); + table weights; + check_compute_result(compute_mode, dense_full, weights, compute_result); + check_for_exception_for_non_requested_results(compute_mode, compute_result); + } + void online_general_checks(const te::dataframe& data_fr, std::shared_ptr weights_fr, bs::result_option_id compute_mode, diff --git a/cpp/oneapi/dal/algo/basic_statistics/test/online.cpp b/cpp/oneapi/dal/algo/basic_statistics/test/online.cpp index 0ff98d8562c..4deaf2036be 100644 --- a/cpp/oneapi/dal/algo/basic_statistics/test/online.cpp +++ b/cpp/oneapi/dal/algo/basic_statistics/test/online.cpp @@ -62,4 +62,29 @@ TEMPLATE_LIST_TEST_M(basic_statistics_online_test, this->online_general_checks(data, weights, compute_mode, nBlocks); } +TEMPLATE_LIST_TEST_M(basic_statistics_online_test, + "basic_statistics common CSR online flow", + "[basic_statistics][integration][online]", + basic_statistics_sparse_types) { + SKIP_IF(this->get_policy().is_gpu()); + SKIP_IF(this->not_float64_friendly()); + const float nnz_fraction = 0.05; + this->data_indexing_ = GENERATE(sparse_indexing::zero_based, sparse_indexing::one_based); + const auto data = + GENERATE_COPY(te::csr_table_builder(5, 5, nnz_fraction, this->data_indexing_), + te::csr_table_builder(7, 10, nnz_fraction, this->data_indexing_), + te::csr_table_builder(100, 100, nnz_fraction, this->data_indexing_)); + SKIP_IF(this->not_cpu_friendly(data)); + + const std::int64_t nBlocks = GENERATE(1, 3, 5); + + const bs::result_option_id res_min_max = result_options::min | result_options::max; + const bs::result_option_id res_mean_varc = result_options::mean | result_options::variance; + const bs::result_option_id res_all = + bs::result_option_id(dal::result_option_id_base(mask_full)); + const bs::result_option_id compute_mode = GENERATE_COPY(res_min_max, res_mean_varc, res_all); + + this->csr_online_general_checks(data, compute_mode, nBlocks); +} + } // namespace oneapi::dal::basic_statistics::test