diff --git a/cpp/daal/include/algorithms/engines/mrg32k3a/mrg32k3a.h b/cpp/daal/include/algorithms/engines/mrg32k3a/mrg32k3a.h new file mode 100644 index 00000000000..a70c1853e1a --- /dev/null +++ b/cpp/daal/include/algorithms/engines/mrg32k3a/mrg32k3a.h @@ -0,0 +1,183 @@ +/* file: mrg32k3a.h */ +/******************************************************************************* +* 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. +*******************************************************************************/ + +/* +//++ +// Implementation of the MRG32k3a engine: a 32-bit combined multiple recursive generator +// with two components of order 3, optimized for batch processing. +//-- +*/ + +#ifndef __MRG32K3A_H__ +#define __MRG32K3A_H__ + +#include "algorithms/engines/mrg32k3a/mrg32k3a_types.h" +#include "algorithms/engines/engine.h" + +namespace daal +{ +namespace algorithms +{ +namespace engines +{ +namespace mrg32k3a +{ +/** + * @defgroup engines_mrg32k3a_batch Batch + * @ingroup engines_mrg32k3a + * @{ + */ +namespace interface1 +{ +/** + * + * \brief Provides methods to run implementations of the mrg32k3a engine. + * This class is associated with the \ref mrg32k3a::interface1::Batch "mrg32k3a::Batch" class + * and supports the method of mrg32k3a engine computation in the batch processing mode + * + * \tparam algorithmFPType Data type to use in intermediate computations of mrg32k3a engine, double or float + * \tparam method Computation method of the engine, mrg32k3a::Method + * \tparam cpu Version of the cpu-specific implementation of the engine, daal::CpuType + */ +template +class BatchContainer : public daal::algorithms::AnalysisContainerIface +{ +public: + /** + * Constructs a container for the mrg32k3a engine with a specified environment + * in the batch processing mode + * \param[in] daalEnv Environment object + */ + BatchContainer(daal::services::Environment::env * daalEnv); + ~BatchContainer(); + /** + * Computes the result of the mrg32k3a engine in the batch processing mode + * + * \return Status of computations + */ + services::Status compute() DAAL_C11_OVERRIDE; +}; + +/** + * + * \brief Provides methods for mrg32k3a engine computations in the batch processing mode + * + * \tparam algorithmFPType Data type to use in intermediate computations of mrg32k3a engine, double or float + * \tparam method Computation method of the engine, mrg32k3a::Method + * + * \par Enumerations + * - mrg32k3a::Method Computation methods for the mrg32k3a engine + * + * \par References + * - \ref engines::interface1::Input "engines::Input" class + * - \ref engines::interface1::Result "engines::Result" class + */ +template +class DAAL_EXPORT Batch : public engines::BatchBase +{ +public: + typedef engines::BatchBase super; + + typedef typename super::InputType InputType; + typedef typename super::ResultType ResultType; + + /** + * Creates mrg32k3a engine + * \param[in] seed Initial condition for mrg32k3a engine + * + * \return Pointer to mrg32k3a engine + */ + static services::SharedPtr > create(size_t seed = 777); + + /** + * Returns method of the engine + * \return Method of the engine + */ + virtual int getMethod() const DAAL_C11_OVERRIDE { return (int)method; } + + /** + * Returns the structure that contains results of mrg32k3a engine + * \return Structure that contains results of mrg32k3a engine + */ + ResultPtr getResult() { return _result; } + + /** + * Registers user-allocated memory to store results of mrg32k3a engine + * \param[in] result Structure to store results of mrg32k3a engine + * + * \return Status of computations + */ + services::Status setResult(const ResultPtr & result) + { + DAAL_CHECK(result, services::ErrorNullResult) + _result = result; + _res = _result.get(); + return services::Status(); + } + + /** + * Returns a pointer to the newly allocated mrg32k3a engine + * with a copy of input objects and parameters of this mrg32k3a engine + * \return Pointer to the newly allocated engine + */ + services::SharedPtr > clone() const { return services::SharedPtr >(cloneImpl()); } + + /** + * Allocates memory to store the result of the mrg32k3a engine + * + * \return Status of computations + */ + virtual services::Status allocateResult() DAAL_C11_OVERRIDE + { + services::Status s = this->_result->template allocate(&(this->input), NULL, (int)method); + this->_res = this->_result.get(); + return s; + } + +protected: + Batch(size_t seed = 777) { initialize(); } + + Batch(const Batch & other) : super(other) { initialize(); } + + virtual Batch * cloneImpl() const DAAL_C11_OVERRIDE { return new Batch(*this); } + + void initialize() + { + Analysis::_ac = new __DAAL_ALGORITHM_CONTAINER(batch, BatchContainer, algorithmFPType, method)(&_env); + _in = &input; + _result.reset(new ResultType()); + } + +private: + ResultPtr _result; + + Batch & operator=(const Batch &); +}; +typedef services::SharedPtr > mrg32k3aPtr; +typedef services::SharedPtr > mrg32k3aConstPtr; + +} // namespace interface1 +using interface1::BatchContainer; +using interface1::Batch; +using interface1::mrg32k3aPtr; +using interface1::mrg32k3aConstPtr; +/** @} */ +} // namespace mrg32k3a +} // namespace engines +} // namespace algorithms +} // namespace daal +#endif diff --git a/cpp/daal/include/algorithms/engines/mrg32k3a/mrg32k3a_types.h b/cpp/daal/include/algorithms/engines/mrg32k3a/mrg32k3a_types.h new file mode 100644 index 00000000000..8fdc58b98c8 --- /dev/null +++ b/cpp/daal/include/algorithms/engines/mrg32k3a/mrg32k3a_types.h @@ -0,0 +1,65 @@ +/* file: mrg32k3a_types.h */ +/******************************************************************************* +* 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. +*******************************************************************************/ + +/* +//++ +// Implementation of the MRG32k3a engine: a 32-bit combined multiple recursive generator +// with two components of order 3, optimized for batch processing. +//-- +*/ + +#ifndef __MRG32K3A_TYPES_H__ +#define __MRG32K3A_TYPES_H__ + +#include "algorithms/algorithm.h" +#include "services/daal_defines.h" +#include "data_management/data/numeric_table.h" +#include "data_management/data/homogen_numeric_table.h" + +namespace daal +{ +namespace algorithms +{ +namespace engines +{ +/** + * @defgroup engines_mrg32k3a mrg32k3a Engine + * \copydoc daal::algorithms::engines::mrg32k3a + * @ingroup engines + * @{ + */ +/** + * \brief Contains classes for mrg32k3a engine + */ +namespace mrg32k3a +{ +/** + * + * Available methods to compute mrg32k3a engine + */ +enum Method +{ + defaultDense = 0 /*!< Default: performance-oriented method. */ +}; + +} // namespace mrg32k3a +/** @} */ +} // namespace engines +} // namespace algorithms +} // namespace daal + +#endif diff --git a/cpp/daal/include/algorithms/engines/philox4x32x10/philox4x32x10.h b/cpp/daal/include/algorithms/engines/philox4x32x10/philox4x32x10.h new file mode 100644 index 00000000000..3a5d0e33180 --- /dev/null +++ b/cpp/daal/include/algorithms/engines/philox4x32x10/philox4x32x10.h @@ -0,0 +1,183 @@ +/* file: philox4x32x10.h */ +/******************************************************************************* +* 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. +*******************************************************************************/ + +/* +//++ +// Implementation of the Philox4x32-10 engine: a counter-based pseudorandom number generator (PRNG) +// that uses 4x32-bit keys and performs 10 rounds of mixing to produce high-quality randomness. +//-- +*/ + +#ifndef __PHILOX4X32X10_H__ +#define __PHILOX4X32X10_H__ + +#include "algorithms/engines/philox4x32x10/philox4x32x10_types.h" +#include "algorithms/engines/engine.h" + +namespace daal +{ +namespace algorithms +{ +namespace engines +{ +namespace philox4x32x10 +{ +/** + * @defgroup engines_philox4x32x10_batch Batch + * @ingroup engines_philox4x32x10 + * @{ + */ +namespace interface1 +{ +/** + * + * \brief Provides methods to run implementations of the philox4x32x10 engine. + * This class is associated with the \ref philox4x32x10::interface1::Batch "philox4x32x10::Batch" class + * and supports the method of philox4x32x10 engine computation in the batch processing mode + * + * \tparam algorithmFPType Data type to use in intermediate computations of philox4x32x10 engine, double or float + * \tparam method Computation method of the engine, philox4x32x10::Method + * \tparam cpu Version of the cpu-specific implementation of the engine, daal::CpuType + */ +template +class BatchContainer : public daal::algorithms::AnalysisContainerIface +{ +public: + /** + * Constructs a container for the philox4x32x10 engine with a specified environment + * in the batch processing mode + * \param[in] daalEnv Environment object + */ + BatchContainer(daal::services::Environment::env * daalEnv); + ~BatchContainer(); + /** + * Computes the result of the philox4x32x10 engine in the batch processing mode + * + * \return Status of computations + */ + services::Status compute() DAAL_C11_OVERRIDE; +}; + +/** + * + * \brief Provides methods for philox4x32x10 engine computations in the batch processing mode + * + * \tparam algorithmFPType Data type to use in intermediate computations of philox4x32x10 engine, double or float + * \tparam method Computation method of the engine, philox4x32x10::Method + * + * \par Enumerations + * - philox4x32x10::Method Computation methods for the philox4x32x10 engine + * + * \par References + * - \ref engines::interface1::Input "engines::Input" class + * - \ref engines::interface1::Result "engines::Result" class + */ +template +class DAAL_EXPORT Batch : public engines::BatchBase +{ +public: + typedef engines::BatchBase super; + + typedef typename super::InputType InputType; + typedef typename super::ResultType ResultType; + + /** + * Creates philox4x32x10 engine + * \param[in] seed Initial condition for philox4x32x10 engine + * + * \return Pointer to philox4x32x10 engine + */ + static services::SharedPtr > create(size_t seed = 777); + + /** + * Returns method of the engine + * \return Method of the engine + */ + virtual int getMethod() const DAAL_C11_OVERRIDE { return (int)method; } + + /** + * Returns the structure that contains results of philox4x32x10 engine + * \return Structure that contains results of philox4x32x10 engine + */ + ResultPtr getResult() { return _result; } + + /** + * Registers user-allocated memory to store results of philox4x32x10 engine + * \param[in] result Structure to store results of philox4x32x10 engine + * + * \return Status of computations + */ + services::Status setResult(const ResultPtr & result) + { + DAAL_CHECK(result, services::ErrorNullResult) + _result = result; + _res = _result.get(); + return services::Status(); + } + + /** + * Returns a pointer to the newly allocated philox4x32x10 engine + * with a copy of input objects and parameters of this philox4x32x10 engine + * \return Pointer to the newly allocated engine + */ + services::SharedPtr > clone() const { return services::SharedPtr >(cloneImpl()); } + + /** + * Allocates memory to store the result of the philox4x32x10 engine + * + * \return Status of computations + */ + virtual services::Status allocateResult() DAAL_C11_OVERRIDE + { + services::Status s = this->_result->template allocate(&(this->input), NULL, (int)method); + this->_res = this->_result.get(); + return s; + } + +protected: + Batch(size_t seed = 777) { initialize(); } + + Batch(const Batch & other) : super(other) { initialize(); } + + virtual Batch * cloneImpl() const DAAL_C11_OVERRIDE { return new Batch(*this); } + + void initialize() + { + Analysis::_ac = new __DAAL_ALGORITHM_CONTAINER(batch, BatchContainer, algorithmFPType, method)(&_env); + _in = &input; + _result.reset(new ResultType()); + } + +private: + ResultPtr _result; + + Batch & operator=(const Batch &); +}; +typedef services::SharedPtr > philox4x32x10Ptr; +typedef services::SharedPtr > philox4x32x10ConstPtr; + +} // namespace interface1 +using interface1::BatchContainer; +using interface1::Batch; +using interface1::philox4x32x10Ptr; +using interface1::philox4x32x10ConstPtr; +/** @} */ +} // namespace philox4x32x10 +} // namespace engines +} // namespace algorithms +} // namespace daal +#endif diff --git a/cpp/daal/include/algorithms/engines/philox4x32x10/philox4x32x10_types.h b/cpp/daal/include/algorithms/engines/philox4x32x10/philox4x32x10_types.h new file mode 100644 index 00000000000..0c0a92c9b3a --- /dev/null +++ b/cpp/daal/include/algorithms/engines/philox4x32x10/philox4x32x10_types.h @@ -0,0 +1,65 @@ +/* file: philox4x32x10_types.h */ +/******************************************************************************* +* 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. +*******************************************************************************/ + +/* +//++ +// Implementation of the Philox4x32-10 engine: a counter-based pseudorandom number generator (PRNG) +// that uses 4x32-bit keys and performs 10 rounds of mixing to produce high-quality randomness. +//-- +*/ + +#ifndef __PHILOX4X32X10_TYPES_H__ +#define __PHILOX4X32X10_TYPES_H__ + +#include "algorithms/algorithm.h" +#include "services/daal_defines.h" +#include "data_management/data/numeric_table.h" +#include "data_management/data/homogen_numeric_table.h" + +namespace daal +{ +namespace algorithms +{ +namespace engines +{ +/** + * @defgroup engines_philox4x32x10 philox4x32x10 Engine + * \copydoc daal::algorithms::engines::philox4x32x10 + * @ingroup engines + * @{ + */ +/** + * \brief Contains classes for philox4x32x10 engine + */ +namespace philox4x32x10 +{ +/** + * + * Available methods to compute philox4x32x10 engine + */ +enum Method +{ + defaultDense = 0 /*!< Default: performance-oriented method. */ +}; + +} // namespace philox4x32x10 +/** @} */ +} // namespace engines +} // namespace algorithms +} // namespace daal + +#endif diff --git a/cpp/daal/include/daal.h b/cpp/daal/include/daal.h index 881a6c39fbe..9e91570ac56 100755 --- a/cpp/daal/include/daal.h +++ b/cpp/daal/include/daal.h @@ -304,6 +304,10 @@ #include "algorithms/engines/engine_family.h" #include "algorithms/engines/mt2203/mt2203.h" #include "algorithms/engines/mt2203/mt2203_types.h" +#include "algorithms/engines/mrg32k3a/mrg32k3a.h" +#include "algorithms/engines/mrg32k3a/mrg32k3a_types.h" +#include "algorithms/engines/philox4x32x10/philox4x32x10.h" +#include "algorithms/engines/philox4x32x10/philox4x32x10_types.h" #include "algorithms/dbscan/dbscan_types.h" #include "algorithms/dbscan/dbscan_batch.h" #include "algorithms/dbscan/dbscan_distributed.h" diff --git a/cpp/daal/include/daal_win.h b/cpp/daal/include/daal_win.h index e17eff16796..6e86076e275 100755 --- a/cpp/daal/include/daal_win.h +++ b/cpp/daal/include/daal_win.h @@ -316,6 +316,10 @@ #include "algorithms/engines/engine_family.h" #include "algorithms/engines/mt2203/mt2203.h" #include "algorithms/engines/mt2203/mt2203_types.h" +#include "algorithms/engines/mrg32k3a/mrg32k3a.h" +#include "algorithms/engines/mrg32k3a/mrg32k3a_types.h" +#include "algorithms/engines/philox4x32x10/philox4x32x10.h" +#include "algorithms/engines/philox4x32x10/philox4x32x10_types.h" #include "algorithms/dbscan/dbscan_types.h" #include "algorithms/dbscan/dbscan_batch.h" #include "algorithms/dbscan/dbscan_distributed.h" diff --git a/cpp/daal/src/algorithms/engines/mcg59/mcg59_batch_impl.h b/cpp/daal/src/algorithms/engines/mcg59/mcg59_batch_impl.h index 6c3040da615..0a9933b57dd 100644 --- a/cpp/daal/src/algorithms/engines/mcg59/mcg59_batch_impl.h +++ b/cpp/daal/src/algorithms/engines/mcg59/mcg59_batch_impl.h @@ -26,9 +26,6 @@ #include "src/externals/service_rng.h" #include "src/data_management/service_numeric_table.h" -static const int leapfrogMethodErrcode = -1002; -static const int skipAheadMethodErrcode = -1003; - namespace daal { namespace algorithms @@ -67,7 +64,7 @@ class BatchImpl : public algorithms::engines::mcg59::interface1::Batch +SharedPtr > Batch::create(size_t seed) +{ + SharedPtr > engPtr; + +#define DAAL_CREATE_ENGINE_CPU(cpuId, ...) engPtr.reset(new BatchImpl(__VA_ARGS__)); + + DAAL_DISPATCH_FUNCTION_BY_CPU(DAAL_CREATE_ENGINE_CPU, seed); + +#undef DAAL_CREATE_ENGINE_CPU + return engPtr; +} + +template class Batch; +template class Batch; + +} // namespace interface1 +} // namespace mrg32k3a +} // namespace engines +} // namespace algorithms +} // namespace daal diff --git a/cpp/daal/src/algorithms/engines/mrg32k3a/mrg32k3a_batch_container.h b/cpp/daal/src/algorithms/engines/mrg32k3a/mrg32k3a_batch_container.h new file mode 100644 index 00000000000..c925b3c4483 --- /dev/null +++ b/cpp/daal/src/algorithms/engines/mrg32k3a/mrg32k3a_batch_container.h @@ -0,0 +1,68 @@ +/* file: mrg32k3a_batch_container.h */ +/******************************************************************************* +* 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. +*******************************************************************************/ + +/* +//++ +// Implementation of mrg32k3a calculation algorithm container. +//-- +*/ + +#ifndef __MRG32K3A_BATCH_CONTAINER_H__ +#define __MRG32K3A_BATCH_CONTAINER_H__ + +#include "algorithms/engines/mrg32k3a/mrg32k3a.h" +#include "src/algorithms/engines/mrg32k3a/mrg32k3a_kernel.h" + +namespace daal +{ +namespace algorithms +{ +namespace engines +{ +namespace mrg32k3a +{ +namespace interface1 +{ +template +BatchContainer::BatchContainer(daal::services::Environment::env * daalEnv) : AnalysisContainerIface(daalEnv) +{ + __DAAL_INITIALIZE_KERNELS(internal::mrg32k3aKernel, algorithmFPType, method); +} + +template +BatchContainer::~BatchContainer() +{ + __DAAL_DEINITIALIZE_KERNELS(); +} + +template +services::Status BatchContainer::compute() +{ + daal::services::Environment::env & env = *_env; + engines::Result * result = static_cast(_res); + NumericTable * resultTable = result->get(engines::randomNumbers).get(); + + __DAAL_CALL_KERNEL(env, internal::mrg32k3aKernel, __DAAL_KERNEL_ARGUMENTS(algorithmFPType, method), compute, resultTable); +} + +} // namespace interface1 +} // namespace mrg32k3a +} // namespace engines +} // namespace algorithms +} // namespace daal + +#endif diff --git a/cpp/daal/src/algorithms/engines/mrg32k3a/mrg32k3a_batch_impl.h b/cpp/daal/src/algorithms/engines/mrg32k3a/mrg32k3a_batch_impl.h new file mode 100644 index 00000000000..0b7048fa95a --- /dev/null +++ b/cpp/daal/src/algorithms/engines/mrg32k3a/mrg32k3a_batch_impl.h @@ -0,0 +1,114 @@ +/* file: mrg32k3a_batch_impl.h */ +/******************************************************************************* +* 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. +*******************************************************************************/ + +/* +//++ +// Implementation of the class defining the mrg32k3a engine. +//-- +*/ + +#include "algorithms/engines/mrg32k3a/mrg32k3a.h" +#include "src/algorithms/engines/engine_batch_impl.h" +#include "src/externals/service_rng.h" +#include "src/data_management/service_numeric_table.h" + +namespace daal +{ +namespace algorithms +{ +namespace engines +{ +namespace mrg32k3a +{ +namespace internal +{ +template +class BatchImpl : public algorithms::engines::mrg32k3a::interface1::Batch, + public algorithms::engines::internal::BatchBaseImpl +{ +public: + typedef algorithms::engines::mrg32k3a::interface1::Batch super1; + typedef algorithms::engines::internal::BatchBaseImpl super2; + BatchImpl(size_t seed = 777) : baseRng(seed, __DAAL_BRNG_MRG32K3A), super2(seed) {} + + void * getState() DAAL_C11_OVERRIDE { return baseRng.getState(); } + + int getStateSize() const DAAL_C11_OVERRIDE { return baseRng.getStateSize(); } + + services::Status saveStateImpl(byte * dest) const DAAL_C11_OVERRIDE + { + DAAL_CHECK(!baseRng.saveState((void *)dest), ErrorIncorrectErrorcodeFromGenerator); + return services::Status(); + } + + services::Status loadStateImpl(const byte * src) DAAL_C11_OVERRIDE + { + DAAL_CHECK(!baseRng.loadState((const void *)src), ErrorIncorrectErrorcodeFromGenerator); + return services::Status(); + } + + services::Status leapfrogImpl(size_t threadNum, size_t nThreads) DAAL_C11_OVERRIDE + { + int errcode = baseRng.leapfrog(threadNum, nThreads); + services::Status s; + if (errcode == __DAAL_LEAPFROG_METHOD_ERRCODE) + s.add(ErrorLeapfrogUnsupported); + else if (errcode) + s.add(ErrorIncorrectErrorcodeFromGenerator); + return s; + } + + services::Status skipAheadImpl(size_t nSkip) DAAL_C11_OVERRIDE + { + int errcode = baseRng.skipAhead(nSkip); + services::Status s; + if (errcode == __DAAL_SKIP_AHEAD_METHOD_ERRCODE) + s.add(ErrorSkipAheadUnsupported); + else if (errcode) + s.add(ErrorIncorrectErrorcodeFromGenerator); + return s; + } + + virtual BatchImpl * cloneImpl() const DAAL_C11_OVERRIDE + { + return new BatchImpl(*this); + } + + bool hasSupport(engines::internal::ParallelizationTechnique technique) const DAAL_C11_OVERRIDE + { + switch (technique) + { + case engines::internal::family: return false; + case engines::internal::skipahead: return true; + case engines::internal::leapfrog: return false; + } + return false; + } + + ~BatchImpl() {} + +protected: + BatchImpl(const BatchImpl & other) : super1(other), super2(other), baseRng(other.baseRng) {} + + daal::internal::BaseRNGsInst baseRng; +}; + +} // namespace internal +} // namespace mrg32k3a +} // namespace engines +} // namespace algorithms +} // namespace daal diff --git a/cpp/daal/src/algorithms/engines/mrg32k3a/mrg32k3a_dense_default_batch_fpt_cpu.cpp b/cpp/daal/src/algorithms/engines/mrg32k3a/mrg32k3a_dense_default_batch_fpt_cpu.cpp new file mode 100644 index 00000000000..529c4af2635 --- /dev/null +++ b/cpp/daal/src/algorithms/engines/mrg32k3a/mrg32k3a_dense_default_batch_fpt_cpu.cpp @@ -0,0 +1,47 @@ +/* file: mrg32k3a_dense_default_batch_fpt_cpu.cpp */ +/******************************************************************************* +* 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. +*******************************************************************************/ + +//++ +// Implementation of mrg32k3a calculation functions. +//-- + +#include "src/algorithms/engines/mrg32k3a/mrg32k3a_batch_container.h" +#include "src/algorithms/engines/mrg32k3a/mrg32k3a_kernel.h" +#include "src/algorithms/engines/mrg32k3a/mrg32k3a_impl.i" + +namespace daal +{ +namespace algorithms +{ +namespace engines +{ +namespace mrg32k3a +{ +namespace interface1 +{ +template class BatchContainer; +} // namespace interface1 + +namespace internal +{ +template class mrg32k3aKernel; +} // namespace internal + +} // namespace mrg32k3a +} // namespace engines +} // namespace algorithms +} // namespace daal diff --git a/cpp/daal/src/algorithms/engines/mrg32k3a/mrg32k3a_dense_default_batch_fpt_dispatcher.cpp b/cpp/daal/src/algorithms/engines/mrg32k3a/mrg32k3a_dense_default_batch_fpt_dispatcher.cpp new file mode 100644 index 00000000000..fd78108df73 --- /dev/null +++ b/cpp/daal/src/algorithms/engines/mrg32k3a/mrg32k3a_dense_default_batch_fpt_dispatcher.cpp @@ -0,0 +1,30 @@ +/* file: mrg32k3a_dense_default_batch_fpt_dispatcher.cpp */ +/******************************************************************************* +* 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. +*******************************************************************************/ + +//++ +// Implementation of mrg32k3a calculation algorithm dispatcher. +//-- + +#include "src/algorithms/engines/mrg32k3a/mrg32k3a_batch_container.h" + +namespace daal +{ +namespace algorithms +{ +__DAAL_INSTANTIATE_DISPATCH_CONTAINER(engines::mrg32k3a::BatchContainer, batch, DAAL_FPTYPE, engines::mrg32k3a::defaultDense) +} // namespace algorithms +} // namespace daal diff --git a/cpp/daal/src/algorithms/engines/mrg32k3a/mrg32k3a_impl.i b/cpp/daal/src/algorithms/engines/mrg32k3a/mrg32k3a_impl.i new file mode 100644 index 00000000000..f8f12b2deea --- /dev/null +++ b/cpp/daal/src/algorithms/engines/mrg32k3a/mrg32k3a_impl.i @@ -0,0 +1,49 @@ +/* file: mrg32k3a_impl.i */ +/******************************************************************************* +* 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. +*******************************************************************************/ + +/* +//++ +// Implementation of mrg32k3a algorithm. +//-- +*/ + +#ifndef __MRG32K3A_IMPL_I__ +#define __MRG32K3A_IMPL_I__ + +namespace daal +{ +namespace algorithms +{ +namespace engines +{ +namespace mrg32k3a +{ +namespace internal +{ +template +Status mrg32k3aKernel::compute(NumericTable * resultTensor) +{ + return Status(); +} + +} // namespace internal +} // namespace mrg32k3a +} // namespace engines +} // namespace algorithms +} // namespace daal + +#endif diff --git a/cpp/daal/src/algorithms/engines/mrg32k3a/mrg32k3a_kernel.h b/cpp/daal/src/algorithms/engines/mrg32k3a/mrg32k3a_kernel.h new file mode 100644 index 00000000000..80c9fbe44d9 --- /dev/null +++ b/cpp/daal/src/algorithms/engines/mrg32k3a/mrg32k3a_kernel.h @@ -0,0 +1,58 @@ +/* file: mrg32k3a_kernel.h */ +/******************************************************************************* +* 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. +*******************************************************************************/ + +//++ +// Declaration of a template function for calculating values using the MRG32k3a generator. +//-- + +#ifndef __MRG32K3A_KERNEL_H__ +#define __MRG32K3A_KERNEL_H__ + +#include "algorithms/engines/mrg32k3a/mrg32k3a.h" +#include "src/algorithms/kernel.h" +#include "data_management/data/numeric_table.h" + +using namespace daal::services; +using namespace daal::data_management; + +namespace daal +{ +namespace algorithms +{ +namespace engines +{ +namespace mrg32k3a +{ +namespace internal +{ +/** + * \brief Kernel for mrg32k3a calculation + */ +template +class mrg32k3aKernel : public Kernel +{ +public: + Status compute(NumericTable * resultTable); +}; + +} // namespace internal +} // namespace mrg32k3a +} // namespace engines +} // namespace algorithms +} // namespace daal + +#endif diff --git a/cpp/daal/src/algorithms/engines/mt19937/mt19937_batch_impl.h b/cpp/daal/src/algorithms/engines/mt19937/mt19937_batch_impl.h index e92d0e46612..b5959d5bfe6 100644 --- a/cpp/daal/src/algorithms/engines/mt19937/mt19937_batch_impl.h +++ b/cpp/daal/src/algorithms/engines/mt19937/mt19937_batch_impl.h @@ -26,9 +26,6 @@ #include "src/externals/service_rng.h" #include "src/data_management/service_numeric_table.h" -static const int leapfrogMethodErrcode = -1002; -static const int skipAheadMethodErrcode = -1003; - namespace daal { namespace algorithms @@ -67,7 +64,7 @@ class BatchImpl : public algorithms::engines::mt19937::interface1::Batchleapfrog(threadNum, nThreads); services::Status s; - if (errcode == leapfrogMethodErrcode) + if (errcode == __DAAL_LEAPFROG_METHOD_ERRCODE) s.add(ErrorLeapfrogUnsupported); else if (errcode) s.add(ErrorIncorrectErrorcodeFromGenerator); @@ -199,7 +196,7 @@ class BatchImpl : public algorithms::engines::mt2203::interface1::BatchskipAhead(nSkip); services::Status s; - if (errcode == skipAheadMethodErrcode) + if (errcode == __DAAL_SKIP_AHEAD_METHOD_ERRCODE) s.add(ErrorSkipAheadUnsupported); else if (errcode) s.add(ErrorIncorrectErrorcodeFromGenerator); diff --git a/cpp/daal/src/algorithms/engines/mt2203/mt2203_kernel.h b/cpp/daal/src/algorithms/engines/mt2203/mt2203_kernel.h index b7de119367f..e588a02c8fb 100644 --- a/cpp/daal/src/algorithms/engines/mt2203/mt2203_kernel.h +++ b/cpp/daal/src/algorithms/engines/mt2203/mt2203_kernel.h @@ -19,8 +19,8 @@ // Declaration of template function that calculate mt2203s. //-- -#ifndef __MCG59_KERNEL_H__ -#define __MCG59_KERNEL_H__ +#ifndef __MT2203_KERNEL_H__ +#define __MT2203_KERNEL_H__ #include "algorithms/engines/mt2203/mt2203.h" #include "src/algorithms/kernel.h" diff --git a/cpp/daal/src/algorithms/engines/philox4x32x10/philox4x32x10.cpp b/cpp/daal/src/algorithms/engines/philox4x32x10/philox4x32x10.cpp new file mode 100644 index 00000000000..47fb7dae70f --- /dev/null +++ b/cpp/daal/src/algorithms/engines/philox4x32x10/philox4x32x10.cpp @@ -0,0 +1,59 @@ +/* file: philox4x32x10.cpp */ +/******************************************************************************* +* 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. +*******************************************************************************/ + +//++ +// Implementation of the Philox4x32-10 engine: a counter-based pseudorandom number generator (PRNG) +// that uses 4x32-bit keys and performs 10 rounds of mixing to produce high-quality randomness. +//-- + +#include "algorithms/engines/philox4x32x10/philox4x32x10.h" +#include "src/externals/service_dispatch.h" +#include "src/algorithms/engines/philox4x32x10/philox4x32x10_batch_impl.h" + +namespace daal +{ +namespace algorithms +{ +namespace engines +{ +namespace philox4x32x10 +{ +namespace interface1 +{ +using namespace daal::services; +using namespace philox4x32x10::internal; + +template +SharedPtr > Batch::create(size_t seed) +{ + SharedPtr > engPtr; +#define DAAL_CREATE_ENGINE_CPU(cpuId, ...) engPtr.reset(new BatchImpl(__VA_ARGS__)); + + DAAL_DISPATCH_FUNCTION_BY_CPU(DAAL_CREATE_ENGINE_CPU, seed); + +#undef DAAL_CREATE_ENGINE_CPU + return engPtr; +} + +template class Batch; +template class Batch; + +} // namespace interface1 +} // namespace philox4x32x10 +} // namespace engines +} // namespace algorithms +} // namespace daal diff --git a/cpp/daal/src/algorithms/engines/philox4x32x10/philox4x32x10_batch_container.h b/cpp/daal/src/algorithms/engines/philox4x32x10/philox4x32x10_batch_container.h new file mode 100644 index 00000000000..9cb747e95a8 --- /dev/null +++ b/cpp/daal/src/algorithms/engines/philox4x32x10/philox4x32x10_batch_container.h @@ -0,0 +1,68 @@ +/* file: philox4x32x10_batch_container.h */ +/******************************************************************************* +* 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. +*******************************************************************************/ + +/* +//++ +// Implementation of philox4x32x10 calculation algorithm container. +//-- +*/ + +#ifndef __PHILOX4X32X10_BATCH_CONTAINER_H__ +#define __PHILOX4X32X10_BATCH_CONTAINER_H__ + +#include "algorithms/engines/philox4x32x10/philox4x32x10.h" +#include "src/algorithms/engines/philox4x32x10/philox4x32x10_kernel.h" + +namespace daal +{ +namespace algorithms +{ +namespace engines +{ +namespace philox4x32x10 +{ +namespace interface1 +{ +template +BatchContainer::BatchContainer(daal::services::Environment::env * daalEnv) : AnalysisContainerIface(daalEnv) +{ + __DAAL_INITIALIZE_KERNELS(internal::philox4x32x10Kernel, algorithmFPType, method); +} + +template +BatchContainer::~BatchContainer() +{ + __DAAL_DEINITIALIZE_KERNELS(); +} + +template +services::Status BatchContainer::compute() +{ + daal::services::Environment::env & env = *_env; + engines::Result * result = static_cast(_res); + NumericTable * resultTable = result->get(engines::randomNumbers).get(); + + __DAAL_CALL_KERNEL(env, internal::philox4x32x10Kernel, __DAAL_KERNEL_ARGUMENTS(algorithmFPType, method), compute, resultTable); +} + +} // namespace interface1 +} // namespace philox4x32x10 +} // namespace engines +} // namespace algorithms +} // namespace daal + +#endif diff --git a/cpp/daal/src/algorithms/engines/philox4x32x10/philox4x32x10_batch_impl.h b/cpp/daal/src/algorithms/engines/philox4x32x10/philox4x32x10_batch_impl.h new file mode 100644 index 00000000000..ebf6b7469ec --- /dev/null +++ b/cpp/daal/src/algorithms/engines/philox4x32x10/philox4x32x10_batch_impl.h @@ -0,0 +1,114 @@ +/* file: philox4x32x10_batch_impl.h */ +/******************************************************************************* +* 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. +*******************************************************************************/ + +/* +//++ +// Implementation of the class defining the philox4x32x10 engine +//-- +*/ + +#include "algorithms/engines/philox4x32x10/philox4x32x10.h" +#include "src/algorithms/engines/engine_batch_impl.h" +#include "src/externals/service_rng.h" +#include "src/data_management/service_numeric_table.h" + +namespace daal +{ +namespace algorithms +{ +namespace engines +{ +namespace philox4x32x10 +{ +namespace internal +{ +template +class BatchImpl : public algorithms::engines::philox4x32x10::interface1::Batch, + public algorithms::engines::internal::BatchBaseImpl +{ +public: + typedef algorithms::engines::philox4x32x10::interface1::Batch super1; + typedef algorithms::engines::internal::BatchBaseImpl super2; + BatchImpl(size_t seed = 777) : baseRng(seed, __DAAL_BRNG_PHILOX4X32X10), super2(seed) {} + + void * getState() DAAL_C11_OVERRIDE { return baseRng.getState(); } + + int getStateSize() const DAAL_C11_OVERRIDE { return baseRng.getStateSize(); } + + services::Status saveStateImpl(byte * dest) const DAAL_C11_OVERRIDE + { + DAAL_CHECK(!baseRng.saveState((void *)dest), ErrorIncorrectErrorcodeFromGenerator); + return services::Status(); + } + + services::Status loadStateImpl(const byte * src) DAAL_C11_OVERRIDE + { + DAAL_CHECK(!baseRng.loadState((const void *)src), ErrorIncorrectErrorcodeFromGenerator); + return services::Status(); + } + + services::Status leapfrogImpl(size_t threadNum, size_t nThreads) DAAL_C11_OVERRIDE + { + int errcode = baseRng.leapfrog(threadNum, nThreads); + services::Status s; + if (errcode == __DAAL_LEAPFROG_METHOD_ERRCODE) + s.add(ErrorLeapfrogUnsupported); + else if (errcode) + s.add(ErrorIncorrectErrorcodeFromGenerator); + return s; + } + + services::Status skipAheadImpl(size_t nSkip) DAAL_C11_OVERRIDE + { + int errcode = baseRng.skipAhead(nSkip); + services::Status s; + if (errcode == __DAAL_SKIP_AHEAD_METHOD_ERRCODE) + s.add(ErrorSkipAheadUnsupported); + else if (errcode) + s.add(ErrorIncorrectErrorcodeFromGenerator); + return s; + } + + virtual BatchImpl * cloneImpl() const DAAL_C11_OVERRIDE + { + return new BatchImpl(*this); + } + + bool hasSupport(engines::internal::ParallelizationTechnique technique) const DAAL_C11_OVERRIDE + { + switch (technique) + { + case engines::internal::family: return false; + case engines::internal::skipahead: return true; + case engines::internal::leapfrog: return false; + } + return false; + } + + ~BatchImpl() {} + +protected: + BatchImpl(const BatchImpl & other) : super1(other), super2(other), baseRng(other.baseRng) {} + + daal::internal::BaseRNGsInst baseRng; +}; + +} // namespace internal +} // namespace philox4x32x10 +} // namespace engines +} // namespace algorithms +} // namespace daal diff --git a/cpp/daal/src/algorithms/engines/philox4x32x10/philox4x32x10_dense_default_batch_fpt_cpu.cpp b/cpp/daal/src/algorithms/engines/philox4x32x10/philox4x32x10_dense_default_batch_fpt_cpu.cpp new file mode 100644 index 00000000000..946517c1d9c --- /dev/null +++ b/cpp/daal/src/algorithms/engines/philox4x32x10/philox4x32x10_dense_default_batch_fpt_cpu.cpp @@ -0,0 +1,47 @@ +/* file: philox4x32x10_dense_default_batch_fpt_cpu.cpp */ +/******************************************************************************* +* 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. +*******************************************************************************/ + +//++ +// Implementation of philox4x32x10 calculation functions. +//-- + +#include "src/algorithms/engines/philox4x32x10/philox4x32x10_batch_container.h" +#include "src/algorithms/engines/philox4x32x10/philox4x32x10_kernel.h" +#include "src/algorithms/engines/philox4x32x10/philox4x32x10_impl.i" + +namespace daal +{ +namespace algorithms +{ +namespace engines +{ +namespace philox4x32x10 +{ +namespace interface1 +{ +template class BatchContainer; +} // namespace interface1 + +namespace internal +{ +template class philox4x32x10Kernel; +} // namespace internal + +} // namespace philox4x32x10 +} // namespace engines +} // namespace algorithms +} // namespace daal diff --git a/cpp/daal/src/algorithms/engines/philox4x32x10/philox4x32x10_dense_default_batch_fpt_dispatcher.cpp b/cpp/daal/src/algorithms/engines/philox4x32x10/philox4x32x10_dense_default_batch_fpt_dispatcher.cpp new file mode 100644 index 00000000000..1640fc4ec12 --- /dev/null +++ b/cpp/daal/src/algorithms/engines/philox4x32x10/philox4x32x10_dense_default_batch_fpt_dispatcher.cpp @@ -0,0 +1,30 @@ +/* file: philox4x32x10_dense_default_batch_fpt_dispatcher.cpp */ +/******************************************************************************* +* 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. +*******************************************************************************/ + +//++ +// Implementation of philox4x32x10 calculation algorithm dispatcher. +//-- + +#include "src/algorithms/engines/philox4x32x10/philox4x32x10_batch_container.h" + +namespace daal +{ +namespace algorithms +{ +__DAAL_INSTANTIATE_DISPATCH_CONTAINER(engines::philox4x32x10::BatchContainer, batch, DAAL_FPTYPE, engines::philox4x32x10::defaultDense) +} // namespace algorithms +} // namespace daal diff --git a/cpp/daal/src/algorithms/engines/philox4x32x10/philox4x32x10_impl.i b/cpp/daal/src/algorithms/engines/philox4x32x10/philox4x32x10_impl.i new file mode 100644 index 00000000000..5aa5addc22b --- /dev/null +++ b/cpp/daal/src/algorithms/engines/philox4x32x10/philox4x32x10_impl.i @@ -0,0 +1,49 @@ +/* file: philox4x32x10_impl.i */ +/******************************************************************************* +* 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. +*******************************************************************************/ + +/* +//++ +// Implementation of philox4x32x10 algorithm. +//-- +*/ + +#ifndef __PHILOX4X32X10_IMPL_I__ +#define __PHILOX4X32X10_IMPL_I__ + +namespace daal +{ +namespace algorithms +{ +namespace engines +{ +namespace philox4x32x10 +{ +namespace internal +{ +template +Status philox4x32x10Kernel::compute(NumericTable * resultTensor) +{ + return Status(); +} + +} // namespace internal +} // namespace philox4x32x10 +} // namespace engines +} // namespace algorithms +} // namespace daal + +#endif diff --git a/cpp/daal/src/algorithms/engines/philox4x32x10/philox4x32x10_kernel.h b/cpp/daal/src/algorithms/engines/philox4x32x10/philox4x32x10_kernel.h new file mode 100644 index 00000000000..5870d781abd --- /dev/null +++ b/cpp/daal/src/algorithms/engines/philox4x32x10/philox4x32x10_kernel.h @@ -0,0 +1,58 @@ +/* file: philox4x32x10_kernel.h */ +/******************************************************************************* +* 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. +*******************************************************************************/ + +//++ +// Declaration of a template function for generating values using the Philox4x32-10 engine. +//-- + +#ifndef __PHILOX4X32X10_KERNEL_H__ +#define __PHILOX4X32X10_KERNEL_H__ + +#include "algorithms/engines/philox4x32x10/philox4x32x10.h" +#include "src/algorithms/kernel.h" +#include "data_management/data/numeric_table.h" + +using namespace daal::services; +using namespace daal::data_management; + +namespace daal +{ +namespace algorithms +{ +namespace engines +{ +namespace philox4x32x10 +{ +namespace internal +{ +/** + * \brief Kernel for philox4x32x10 calculation + */ +template +class philox4x32x10Kernel : public Kernel +{ +public: + Status compute(NumericTable * resultTable); +}; + +} // namespace internal +} // namespace philox4x32x10 +} // namespace engines +} // namespace algorithms +} // namespace daal + +#endif diff --git a/cpp/daal/src/externals/service_rng_mkl.h b/cpp/daal/src/externals/service_rng_mkl.h index b2dcd81b78b..14f6fcc8c06 100644 --- a/cpp/daal/src/externals/service_rng_mkl.h +++ b/cpp/daal/src/externals/service_rng_mkl.h @@ -32,6 +32,8 @@ #define __DAAL_BRNG_MT2203 VSL_BRNG_MT2203 #define __DAAL_BRNG_MT19937 VSL_BRNG_MT19937 #define __DAAL_BRNG_MCG59 VSL_BRNG_MCG59 +#define __DAAL_BRNG_MRG32K3A VSL_BRNG_MRG32K3A +#define __DAAL_BRNG_PHILOX4X32X10 VSL_BRNG_PHILOX4X32X10 #define __DAAL_RNG_METHOD_UNIFORM_STD VSL_RNG_METHOD_UNIFORM_STD #define __DAAL_RNG_METHOD_UNIFORMBITS32_STD 0 #define __DAAL_RNG_METHOD_BERNOULLI_ICDF VSL_RNG_METHOD_BERNOULLI_ICDF @@ -39,6 +41,10 @@ #define __DAAL_RNG_METHOD_GAUSSIAN_BOXMULLER2 VSL_RNG_METHOD_GAUSSIAN_BOXMULLER2 #define __DAAL_RNG_METHOD_GAUSSIAN_ICDF VSL_RNG_METHOD_GAUSSIAN_ICDF +// Errors +#define __DAAL_LEAPFROG_METHOD_ERRCODE VSL_RNG_ERROR_LEAPFROG_UNSUPPORTED +#define __DAAL_SKIP_AHEAD_METHOD_ERRCODE VSL_RNG_ERROR_SKIPAHEAD_UNSUPPORTED + namespace daal { namespace internal diff --git a/cpp/daal/src/externals/service_rng_openrng.h b/cpp/daal/src/externals/service_rng_openrng.h index dd70c644606..d8109ccc366 100644 --- a/cpp/daal/src/externals/service_rng_openrng.h +++ b/cpp/daal/src/externals/service_rng_openrng.h @@ -25,6 +25,8 @@ #define __DAAL_BRNG_MT2203 VSL_BRNG_MT2203 #define __DAAL_BRNG_MT19937 VSL_BRNG_MT19937 #define __DAAL_BRNG_MCG59 VSL_BRNG_MCG59 +#define __DAAL_BRNG_MRG32K3A VSL_BRNG_MRG32K3A +#define __DAAL_BRNG_PHILOX4X32X10 VSL_BRNG_PHILOX4X32X10 #define __DAAL_RNG_METHOD_UNIFORM_STD VSL_RNG_METHOD_UNIFORM_STD #define __DAAL_RNG_METHOD_UNIFORMBITS32_STD 0 #define __DAAL_RNG_METHOD_BERNOULLI_ICDF VSL_RNG_METHOD_BERNOULLI_ICDF @@ -32,6 +34,10 @@ #define __DAAL_RNG_METHOD_GAUSSIAN_BOXMULLER2 VSL_RNG_METHOD_GAUSSIAN_BOXMULLER2 #define __DAAL_RNG_METHOD_GAUSSIAN_ICDF VSL_RNG_METHOD_GAUSSIAN_ICDF +// Erros +#define __DAAL_LEAPFROG_METHOD_ERRCODE VSL_RNG_ERROR_LEAPFROG_UNSUPPORTED +#define __DAAL_SKIP_AHEAD_METHOD_ERRCODE VSL_RNG_ERROR_SKIPAHEAD_UNSUPPORTED + namespace daal { namespace internal diff --git a/cpp/daal/src/externals/service_rng_ref.h b/cpp/daal/src/externals/service_rng_ref.h index fc56fcf6205..3957a895226 100644 --- a/cpp/daal/src/externals/service_rng_ref.h +++ b/cpp/daal/src/externals/service_rng_ref.h @@ -36,16 +36,22 @@ #include // RNGs - #define __DAAL_BRNG_MT2203 (1 << 20) * 9 //VSL_BRNG_MT2203 - #define __DAAL_BRNG_MT19937 (1 << 20) * 8 //VSL_BRNG_MT19937 - #define __DAAL_BRNG_MCG59 (1 << 20) * 4 //VSL_BRNG_MCG59 + #define __DAAL_BRNG_MT2203 (1 << 20) * 9 //VSL_BRNG_MT2203 + #define __DAAL_BRNG_MT19937 (1 << 20) * 8 //VSL_BRNG_MT19937 + #define __DAAL_BRNG_MCG59 (1 << 20) * 4 //VSL_BRNG_MCG59 + #define __DAAL_BRNG_MRG32K3A (1 << 20) * 3 //VSL_BRNG_MRG32K3A + #define __DAAL_BRNG_PHILOX4X32X10 (1 << 20) * 16 //VSL_BRNG_PHILOX4X32X10 #define __DAAL_RNG_METHOD_UNIFORM_STD 0 //VSL_RNG_METHOD_UNIFORM_STD #define __DAAL_RNG_METHOD_UNIFORMBITS32_STD 4 - #define __DAAL_RNG_METHOD_BERNOULLI_ICDF 0 //VSL_RNG_METHOD_BERNOULLI_ICDF - #define __DAAL_RNG_METHOD_GAUSSIAN_BOXMULLER 0 //VSL_RNG_METHOD_GAUSSIAN_BOXMULLER - #define __DAAL_RNG_METHOD_GAUSSIAN_BOXMULLER2 1 //VSL_RNG_METHOD_GAUSSIAN_BOXMULLER2 - #define __DAAL_RNG_METHOD_GAUSSIAN_ICDF 2 //VSL_RNG_METHOD_GAUSSIAN_ICDF + #define __DAAL_RNG_METHOD_BERNOULLI_ICDF 0 //VSL_RNG_METHOD_BERNOULLI_ICDF + #define __DAAL_RNG_METHOD_GAUSSIAN_BOXMULLER 0 //VSL_RNG_METHOD_GAUSSIAN_BOXMULLER + #define __DAAL_RNG_METHOD_GAUSSIAN_BOXMULLER2 1 //VSL_RNG_METHOD_GAUSSIAN_BOXMULLER2 + #define __DAAL_RNG_METHOD_GAUSSIAN_ICDF 2 //VSL_RNG_METHOD_GAUSSIAN_ICDF + + // Errors + #define __DAAL_LEAPFROG_METHOD_ERRCODE -1002 // VSL_RNG_ERROR_LEAPFROG_UNSUPPORTED + #define __DAAL_SKIP_AHEAD_METHOD_ERRCODE -1003 // VSL_RNG_ERROR_SKIPAHEAD_UNSUPPORTED namespace daal { diff --git a/cpp/oneapi/dal/algo/connected_components/backend/cpu/vertex_partitioning_default_kernel.hpp b/cpp/oneapi/dal/algo/connected_components/backend/cpu/vertex_partitioning_default_kernel.hpp index 4da1866e277..497e98427e2 100644 --- a/cpp/oneapi/dal/algo/connected_components/backend/cpu/vertex_partitioning_default_kernel.hpp +++ b/cpp/oneapi/dal/algo/connected_components/backend/cpu/vertex_partitioning_default_kernel.hpp @@ -24,7 +24,7 @@ #include "oneapi/dal/backend/memory.hpp" #include "oneapi/dal/backend/interop/common.hpp" #include "oneapi/dal/table/homogen.hpp" -#include "oneapi/dal/backend/primitives/rng/rng_engine.hpp" +#include "oneapi/dal/backend/primitives/rng/host_engine.hpp" #include "oneapi/dal/detail/threading.hpp" namespace oneapi::dal::preview::connected_components::backend { @@ -90,9 +90,12 @@ std::int32_t most_frequent_element(const std::atomic *components, const std::int64_t &samples_count = 1024) { std::int32_t *rnd_vertex_ids = allocate(vertex_allocator, samples_count); - dal::backend::primitives::engine eng; - dal::backend::primitives::rng rn_gen; - rn_gen.uniform(samples_count, rnd_vertex_ids, eng.get_state(), 0, vertex_count); + dal::backend::primitives::host_engine eng; + dal::backend::primitives::uniform(samples_count, + rnd_vertex_ids, + eng, + 0, + vertex_count); std::int32_t *root_sample_counts = allocate(vertex_allocator, vertex_count); diff --git a/cpp/oneapi/dal/algo/decision_forest/backend/gpu/train_kernel_hist_impl.hpp b/cpp/oneapi/dal/algo/decision_forest/backend/gpu/train_kernel_hist_impl.hpp index 9dfe252e849..64dbae4c084 100644 --- a/cpp/oneapi/dal/algo/decision_forest/backend/gpu/train_kernel_hist_impl.hpp +++ b/cpp/oneapi/dal/algo/decision_forest/backend/gpu/train_kernel_hist_impl.hpp @@ -21,7 +21,7 @@ #include "oneapi/dal/backend/primitives/utils.hpp" #include "oneapi/dal/algo/decision_forest/train_types.hpp" -#include "oneapi/dal/backend/primitives/rng/rng_engine_collection.hpp" +#include "oneapi/dal/backend/primitives/rng/host_engine_collection.hpp" #include "oneapi/dal/algo/decision_forest/backend/gpu/train_misc_structs.hpp" #include "oneapi/dal/algo/decision_forest/backend/gpu/train_impurity_data.hpp" @@ -50,7 +50,7 @@ class train_kernel_hist_impl { using model_manager_t = train_model_manager; using train_context_t = train_context; using imp_data_t = impurity_data; - using rng_engine_t = pr::engine; + using rng_engine_t = pr::host_engine; using rng_engine_list_t = std::vector; using msg = dal::detail::error_messages; using comm_t = bk::communicator; diff --git a/cpp/oneapi/dal/algo/decision_forest/backend/gpu/train_kernel_hist_impl_dpc.cpp b/cpp/oneapi/dal/algo/decision_forest/backend/gpu/train_kernel_hist_impl_dpc.cpp index fc875683784..d1a6a803e6f 100644 --- a/cpp/oneapi/dal/algo/decision_forest/backend/gpu/train_kernel_hist_impl_dpc.cpp +++ b/cpp/oneapi/dal/algo/decision_forest/backend/gpu/train_kernel_hist_impl_dpc.cpp @@ -56,6 +56,22 @@ struct float_accuracy { static constexpr double val = double(1e-10); }; +pr::engine_method convert_engine_method(df_engine_types method) { + switch (method) { + case df_engine_types::mt2203: + return ::oneapi::dal::backend::primitives::engine_method::mt2203; + case df_engine_types::mcg59: + return ::oneapi::dal::backend::primitives::engine_method::mcg59; + case df_engine_types::mrg32k3a: + return ::oneapi::dal::backend::primitives::engine_method::mrg32k3a; + case df_engine_types::philox4x32x10: + return ::oneapi::dal::backend::primitives::engine_method::philox4x32x10; + case df_engine_types::mt19937: + return ::oneapi::dal::backend::primitives::engine_method::mt19937; + default: throw std::invalid_argument("Unsupported engine type 2"); + } +} + template void train_kernel_hist_impl::validate_input(const descriptor_t& desc, const table& data, @@ -396,14 +412,13 @@ sycl::event train_kernel_hist_impl::gen_initial_tree_or Index* const node_list_ptr = node_list_host.get_mutable_data(); for (Index node_idx = 0; node_idx < node_count; ++node_idx) { - pr::rng rn_gen; Index* gen_row_idx_global_ptr = selected_row_global_ptr + ctx.selected_row_total_count_ * node_idx; - rn_gen.uniform(ctx.selected_row_total_count_, - gen_row_idx_global_ptr, - rng_engine_list[engine_offset + node_idx].get_state(), - 0, - ctx.row_total_count_); + pr::uniform(ctx.selected_row_total_count_, + gen_row_idx_global_ptr, + rng_engine_list[engine_offset + node_idx], + 0, + ctx.row_total_count_); if (ctx.distr_mode_) { Index* node_ptr = node_list_ptr + node_idx * impl_const_t::node_prop_count_; @@ -483,15 +498,14 @@ train_kernel_hist_impl::gen_feature_list( auto node_vs_tree_map_list_host = node_vs_tree_map_list.to_host(queue_); - pr::rng rn_gen; auto tree_map_ptr = node_vs_tree_map_list_host.get_mutable_data(); if (ctx.selected_ftr_count_ != ctx.column_count_) { for (Index node = 0; node < node_count; ++node) { - rn_gen.uniform_without_replacement( + pr::uniform_without_replacement( ctx.selected_ftr_count_, selected_features_host_ptr + node * ctx.selected_ftr_count_, selected_features_host_ptr + (node + 1) * ctx.selected_ftr_count_, - rng_engine_list[tree_map_ptr[node]].get_state(), + rng_engine_list[tree_map_ptr[node]], 0, ctx.column_count_); } @@ -524,7 +538,6 @@ train_kernel_hist_impl::gen_random_thresholds( auto node_vs_tree_map_list_host = node_vs_tree_map.to_host(queue_); - pr::rng rn_gen; auto tree_map_ptr = node_vs_tree_map_list_host.get_mutable_data(); // Create arrays for random generated bins @@ -537,11 +550,11 @@ train_kernel_hist_impl::gen_random_thresholds( // Generate random bins for selected features for (Index node = 0; node < node_count; ++node) { - rn_gen.uniform(ctx.selected_ftr_count_, - random_bins_host_ptr + node * ctx.selected_ftr_count_, - rng_engine_list[tree_map_ptr[node]].get_state(), - 0.0f, - 1.0f); + pr::uniform(ctx.selected_ftr_count_, + random_bins_host_ptr + node * ctx.selected_ftr_count_, + rng_engine_list[tree_map_ptr[node]], + 0.0f, + 1.0f); } auto event_rnd_generate = random_bins_com.assign_from_host(queue_, random_bins_host_ptr, random_bins_com.get_count()); @@ -1660,12 +1673,10 @@ sycl::event train_kernel_hist_impl::compute_results( const Float div1 = Float(1) / Float(built_tree_count + tree_idx_in_block + 1); - pr::rng rn_gen; - for (Index column_idx = 0; column_idx < ctx.column_count_; ++column_idx) { - rn_gen.shuffle(oob_row_count, - permutation_ptr, - engine_arr[built_tree_count + tree_idx_in_block].get_state()); + pr::shuffle(oob_row_count, + permutation_ptr, + engine_arr[built_tree_count + tree_idx_in_block]); const Float oob_err_perm = compute_oob_error_perm(ctx, model_manager, data_host, @@ -1857,8 +1868,8 @@ train_result train_kernel_hist_impl::operator()( skip_num = de::check_mul_overflow(ctx.tree_count_, skip_num); de::check_mul_overflow((ctx.tree_count_ - 1), skip_num); - - pr::engine_collection collection(ctx.tree_count_, desc.get_seed()); + auto engine_method = convert_engine_method(desc.get_engine_method()); + pr::engine_collection collection(ctx.tree_count_, desc.get_seed(), engine_method); rng_engine_list_t engine_arr = collection([&](std::size_t i, std::size_t& skip) { skip = i * skip_num; }); diff --git a/cpp/oneapi/dal/algo/decision_forest/backend/gpu/train_splitter_impl.hpp b/cpp/oneapi/dal/algo/decision_forest/backend/gpu/train_splitter_impl.hpp index 2cadc5f72ae..b8e109568fe 100644 --- a/cpp/oneapi/dal/algo/decision_forest/backend/gpu/train_splitter_impl.hpp +++ b/cpp/oneapi/dal/algo/decision_forest/backend/gpu/train_splitter_impl.hpp @@ -19,7 +19,7 @@ #include "oneapi/dal/table/common.hpp" #include "oneapi/dal/backend/primitives/ndarray.hpp" #include "oneapi/dal/backend/primitives/utils.hpp" -#include "oneapi/dal/backend/primitives/rng/rng_engine_collection.hpp" +#include "oneapi/dal/backend/primitives/rng/host_engine_collection.hpp" #include "oneapi/dal/algo/decision_forest/train_types.hpp" #include "oneapi/dal/algo/decision_forest/backend/gpu/train_misc_structs.hpp" diff --git a/cpp/oneapi/dal/algo/decision_forest/common.cpp b/cpp/oneapi/dal/algo/decision_forest/common.cpp index 1b15dd83220..7a11dbfc295 100644 --- a/cpp/oneapi/dal/algo/decision_forest/common.cpp +++ b/cpp/oneapi/dal/algo/decision_forest/common.cpp @@ -61,6 +61,7 @@ class descriptor_impl : public base { error_metric_mode error_metric_mode_value = error_metric_mode::none; infer_mode infer_mode_value = infer_mode::class_responses; + df_engine_types engine_method = df_engine_types::mt2203; bool memory_saving_mode = false; bool bootstrap = true; splitter_mode splitter_mode_value = splitter_mode::best; @@ -179,6 +180,11 @@ std::int64_t descriptor_base::get_seed() const { return impl_->seed; } +template +df_engine_types descriptor_base::get_engine_method() const { + return impl_->engine_method; +} + template void descriptor_base::set_observations_per_tree_fraction_impl(double value) { check_domain_cond((value > 0.0 && value <= 1.0), @@ -299,6 +305,11 @@ void descriptor_base::set_seed_impl(std::int64_t value) { impl_->seed = value; } +template +void descriptor_base::set_engine_method_impl(df_engine_types value) { + impl_->engine_method = value; +} + template class ONEDAL_EXPORT descriptor_base; template class ONEDAL_EXPORT descriptor_base; diff --git a/cpp/oneapi/dal/algo/decision_forest/common.hpp b/cpp/oneapi/dal/algo/decision_forest/common.hpp index 0350002c83d..082e9f8c5f0 100644 --- a/cpp/oneapi/dal/algo/decision_forest/common.hpp +++ b/cpp/oneapi/dal/algo/decision_forest/common.hpp @@ -133,6 +133,17 @@ enum class splitter_mode { random }; +/// Available splitting strategies for building trees +enum class df_engine_types { + /// Threshold for a node is chosen as the best among all bins + mt2203, + /// Threshold for a node is the best for a set chosen at random + mcg59, + philox4x32x10, + mt19937, + mrg32k3a +}; + inline infer_mode operator|(infer_mode value_left, infer_mode value_right) { return bitwise_or(value_left, value_right); } @@ -176,6 +187,7 @@ using v1::error_metric_mode; using v1::infer_mode; using v1::voting_mode; using v1::splitter_mode; +using v1::df_engine_types; namespace detail { namespace v1 { @@ -249,6 +261,7 @@ class descriptor_base : public base { return get_voting_mode_impl(); } + df_engine_types get_engine_method() const; std::int64_t get_seed() const; protected: @@ -277,6 +290,7 @@ class descriptor_base : public base { infer_mode get_infer_mode_impl() const; voting_mode get_voting_mode_impl() const; + void set_engine_method_impl(df_engine_types value); void set_seed_impl(std::int64_t value); private: @@ -594,6 +608,15 @@ class descriptor : public detail::descriptor_base { return *this; } + df_engine_types get_engine_method() const { + return base_t::get_engine_method(); + } + + auto& set_engine_method(df_engine_types value) { + base_t::set_engine_method_impl(value); + return *this; + } + /// Seed for the random numbers generator used by the algorithm /// @invariant :expr:`tree_count > 0` std::int64_t get_seed() const { diff --git a/cpp/oneapi/dal/algo/louvain/backend/cpu/louvain_data.hpp b/cpp/oneapi/dal/algo/louvain/backend/cpu/louvain_data.hpp index d21de8c9627..b41ef0e23a6 100644 --- a/cpp/oneapi/dal/algo/louvain/backend/cpu/louvain_data.hpp +++ b/cpp/oneapi/dal/algo/louvain/backend/cpu/louvain_data.hpp @@ -17,7 +17,7 @@ #pragma once #include "oneapi/dal/backend/memory.hpp" -#include "oneapi/dal/backend/primitives/rng/rng_engine.hpp" +#include "oneapi/dal/backend/primitives/rng/host_engine.hpp" namespace oneapi::dal::preview::louvain::backend { using namespace oneapi::dal::preview::detail; @@ -123,8 +123,7 @@ struct louvain_data { // Total link weight in the network value_type m; - engine eng; - rng rn_gen; + host_engine eng; const std::int64_t vertex_count; const std::int64_t edge_count; diff --git a/cpp/oneapi/dal/algo/louvain/backend/cpu/vertex_partitioning_default_kernel.hpp b/cpp/oneapi/dal/algo/louvain/backend/cpu/vertex_partitioning_default_kernel.hpp index 79e294e9f47..e287c3f2f66 100644 --- a/cpp/oneapi/dal/algo/louvain/backend/cpu/vertex_partitioning_default_kernel.hpp +++ b/cpp/oneapi/dal/algo/louvain/backend/cpu/vertex_partitioning_default_kernel.hpp @@ -206,7 +206,7 @@ inline Float move_nodes(const dal::preview::detail::topology& t, ld.random_order[index] = index; } // random shuffle - ld.rn_gen.uniform(t._vertex_count, ld.index, ld.eng.get_state(), 0, t._vertex_count); + uniform(t._vertex_count, ld.index, ld.eng, 0, t._vertex_count); for (std::int64_t index = 0; index < t._vertex_count; ++index) { std::swap(ld.random_order[index], ld.random_order[ld.index[index]]); } diff --git a/cpp/oneapi/dal/backend/primitives/objective_function/test/fixture.hpp b/cpp/oneapi/dal/backend/primitives/objective_function/test/fixture.hpp index d22a2dde0a1..8eaee870d3a 100644 --- a/cpp/oneapi/dal/backend/primitives/objective_function/test/fixture.hpp +++ b/cpp/oneapi/dal/backend/primitives/objective_function/test/fixture.hpp @@ -25,7 +25,7 @@ #include "oneapi/dal/table/csr_accessor.hpp" #include "oneapi/dal/detail/debug.hpp" -#include "oneapi/dal/backend/primitives/rng/rng_engine.hpp" +#include "oneapi/dal/backend/primitives/rng/host_engine.hpp" namespace oneapi::dal::backend::primitives::test { @@ -572,13 +572,12 @@ class logloss_test : public te::float_algo_fixture rn_gen; auto vec_host = ndarray::empty(this->get_queue(), { dim }, sycl::usm::alloc::host); for (std::int32_t ij = 0; ij < num_checks; ++ij) { - primitives::engine eng(2007 + dim * num_checks + ij); - rn_gen.uniform(dim, vec_host.get_mutable_data(), eng.get_state(), -1.0, 1.0); + primitives::host_engine eng(2007 + dim * num_checks + ij); + primitives::uniform(dim, vec_host.get_mutable_data(), eng, -1.0, 1.0); auto vec_gpu = vec_host.to_device(this->get_queue()); auto out_vector = ndarray::empty(this->get_queue(), { dim }, sycl::usm::alloc::device); diff --git a/cpp/oneapi/dal/backend/primitives/objective_function/test/spmd_fixture.hpp b/cpp/oneapi/dal/backend/primitives/objective_function/test/spmd_fixture.hpp index e902dd452e1..63ab0a07c13 100644 --- a/cpp/oneapi/dal/backend/primitives/objective_function/test/spmd_fixture.hpp +++ b/cpp/oneapi/dal/backend/primitives/objective_function/test/spmd_fixture.hpp @@ -100,12 +100,12 @@ class logloss_spmd_test : public logloss_test { std::int64_t num_checks = 5; std::vector> vecs_host(num_checks), vecs_gpu(num_checks); - rng rn_gen; + for (std::int64_t ij = 0; ij < num_checks; ++ij) { - engine eng(2007 + dim * num_checks + ij); + host_engine eng(2007 + dim * num_checks + ij); vecs_host[ij] = (ndarray::empty(this->get_queue(), { dim }, sycl::usm::alloc::host)); - rn_gen.uniform(dim, vecs_host[ij].get_mutable_data(), eng.get_state(), -1.0, 1.0); + uniform(dim, vecs_host[ij].get_mutable_data(), eng, -1.0, 1.0); vecs_gpu[ij] = vecs_host[ij].to_device(this->get_queue()); } diff --git a/cpp/oneapi/dal/backend/primitives/optimizers/test/cg_solver_dpc.cpp b/cpp/oneapi/dal/backend/primitives/optimizers/test/cg_solver_dpc.cpp index ea320f690a2..6ac19ef1cbe 100644 --- a/cpp/oneapi/dal/backend/primitives/optimizers/test/cg_solver_dpc.cpp +++ b/cpp/oneapi/dal/backend/primitives/optimizers/test/cg_solver_dpc.cpp @@ -20,7 +20,7 @@ #include "oneapi/dal/test/engine/common.hpp" #include "oneapi/dal/test/engine/fixtures.hpp" #include "oneapi/dal/table/row_accessor.hpp" -#include "oneapi/dal/backend/primitives/rng/rng_engine.hpp" +#include "oneapi/dal/backend/primitives/rng/host_engine.hpp" #include namespace oneapi::dal::backend::primitives::test { @@ -43,9 +43,8 @@ class cg_solver_test : public te::float_algo_fixture { x_host_ = ndarray::empty(this->get_queue(), { n_ }, sycl::usm::alloc::host); b_host_ = ndarray::empty(this->get_queue(), { n_ }, sycl::usm::alloc::host); - primitives::rng rn_gen; - primitives::engine eng(4014 + n_); - rn_gen.uniform(n_, x_host_.get_mutable_data(), eng.get_state(), -1.0, 1.0); + primitives::host_engine eng(4014 + n_); + primitives::uniform(n_, x_host_.get_mutable_data(), eng, -1.0, 1.0); create_stable_matrix(this->get_queue(), A_host_); diff --git a/cpp/oneapi/dal/backend/primitives/optimizers/test/fixture.hpp b/cpp/oneapi/dal/backend/primitives/optimizers/test/fixture.hpp index a6b87b2dcc1..a397246a9a7 100644 --- a/cpp/oneapi/dal/backend/primitives/optimizers/test/fixture.hpp +++ b/cpp/oneapi/dal/backend/primitives/optimizers/test/fixture.hpp @@ -21,7 +21,7 @@ #include "oneapi/dal/backend/primitives/ndarray.hpp" #include "oneapi/dal/test/engine/common.hpp" #include "oneapi/dal/test/engine/fixtures.hpp" -#include "oneapi/dal/backend/primitives/rng/rng_engine.hpp" +#include "oneapi/dal/backend/primitives/rng/host_engine.hpp" #include "oneapi/dal/backend/primitives/blas/gemv.hpp" #include "oneapi/dal/backend/primitives/element_wise.hpp" @@ -133,11 +133,10 @@ void create_stable_matrix(sycl::queue& queue, ONEDAL_ASSERT(A.get_dimension(1) == n); auto J = ndarray::empty(queue, { n, n }, sycl::usm::alloc::host); auto eigen_values = ndarray::empty(queue, { n }, sycl::usm::alloc::host); - primitives::rng rn_gen; - primitives::engine eng(2007 + n); + primitives::host_engine eng(2007 + n); - rn_gen.uniform(n * n, J.get_mutable_data(), eng.get_state(), -1.0, 1.0); - rn_gen.uniform(n, eigen_values.get_mutable_data(), eng.get_state(), bottom_eig, top_eig); + primitives::uniform(n * n, J.get_mutable_data(), eng, -1.0, 1.0); + primitives::uniform(n, eigen_values.get_mutable_data(), eng, bottom_eig, top_eig); // orthogonalize matrix J gram_schmidt(J); diff --git a/cpp/oneapi/dal/backend/primitives/optimizers/test/newton_cg_dpc.cpp b/cpp/oneapi/dal/backend/primitives/optimizers/test/newton_cg_dpc.cpp index f473dddf1f7..ad2faabeff8 100644 --- a/cpp/oneapi/dal/backend/primitives/optimizers/test/newton_cg_dpc.cpp +++ b/cpp/oneapi/dal/backend/primitives/optimizers/test/newton_cg_dpc.cpp @@ -22,7 +22,7 @@ #include "oneapi/dal/test/engine/common.hpp" #include "oneapi/dal/test/engine/fixtures.hpp" #include "oneapi/dal/table/row_accessor.hpp" -#include "oneapi/dal/backend/primitives/rng/rng_engine.hpp" +#include "oneapi/dal/backend/primitives/rng/host_engine.hpp" #include #include "oneapi/dal/backend/primitives/objective_function.hpp" @@ -56,10 +56,10 @@ class newton_cg_test : public te::float_algo_fixture { ndarray::empty(this->get_queue(), { n_ + 1 }, sycl::usm::alloc::host); auto params_host = ndarray::empty(this->get_queue(), { p_ + 1 }, sycl::usm::alloc::host); - primitives::rng rn_gen; - primitives::engine eng(2007 + n); - rn_gen.uniform(n_ * p_, X_host.get_mutable_data(), eng.get_state(), -10.0, 10.0); - rn_gen.uniform(p_ + 1, params_host.get_mutable_data(), eng.get_state(), -5.0, 5.0); + + primitives::host_engine eng(2007 + n); + primitives::uniform(n_ * p_, X_host.get_mutable_data(), eng, -10.0, 10.0); + primitives::uniform(p_ + 1, params_host.get_mutable_data(), eng, -5.0, 5.0); for (std::int64_t i = 0; i < n_; ++i) { float_t val = 0; for (std::int64_t j = 0; j < p_; ++j) { @@ -142,9 +142,8 @@ class newton_cg_test : public te::float_algo_fixture { ndarray::empty(this->get_queue(), { n_, n_ }, sycl::usm::alloc::host); solution_ = ndarray::empty(this->get_queue(), { n_ }, sycl::usm::alloc::host); auto b_host = ndarray::empty(this->get_queue(), { n_ }, sycl::usm::alloc::host); - primitives::rng rn_gen; - primitives::engine eng(4014 + n_); - rn_gen.uniform(n_, solution_.get_mutable_data(), eng.get_state(), -1.0, 1.0); + primitives::host_engine eng(4014 + n_); + uniform(n_, solution_.get_mutable_data(), eng, -1.0, 1.0); create_stable_matrix(this->get_queue(), A_host, float_t(0.1), float_t(5.0)); @@ -164,7 +163,7 @@ class newton_cg_test : public te::float_algo_fixture { auto buffer = ndarray::empty(this->get_queue(), { n_ }, sycl::usm::alloc::host); for (std::int32_t test_num = 0; test_num < 5; ++test_num) { - rn_gen.uniform(n_, x_host.get_mutable_data(), eng.get_state(), -1.0, 1.0); + uniform(n_, x_host.get_mutable_data(), eng, -1.0, 1.0); auto x_gpu = x_host.to_device(this->get_queue()); auto compute_event_vec = func_->update_x(x_gpu, true, {}); wait_or_pass(compute_event_vec).wait_and_throw(); diff --git a/cpp/oneapi/dal/backend/primitives/rng/dpc_engine.hpp b/cpp/oneapi/dal/backend/primitives/rng/dpc_engine.hpp new file mode 100644 index 00000000000..e406780442a --- /dev/null +++ b/cpp/oneapi/dal/backend/primitives/rng/dpc_engine.hpp @@ -0,0 +1,384 @@ +/******************************************************************************* +* 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. +*******************************************************************************/ + +#pragma once + +#include "oneapi/dal/backend/primitives/rng/utils.hpp" +#include "oneapi/dal/backend/primitives/rng/rng_types.hpp" + +#include +#include +#include +#include +#include + +#include + +namespace mkl = oneapi::mkl; +namespace oneapi::dal::backend::primitives { + +#ifdef ONEDAL_DATA_PARALLEL + +class gen_base { +public: + virtual ~gen_base() = default; + virtual engine_method get_engine_method() const = 0; + virtual void skip_ahead_gpu(std::int64_t nSkip) = 0; +}; + +class gen_mt2203 : public gen_base { +public: + explicit gen_mt2203() = delete; + gen_mt2203(sycl::queue queue, std::int64_t seed) : _gen(queue, seed, 0) {} + + engine_method get_engine_method() const override { + return engine_method::mt2203; + } + void skip_ahead_gpu(std::int64_t nSkip) override { + //skip; + } + oneapi::mkl::rng::mt2203* get() { + return &_gen; + } + +protected: + oneapi::mkl::rng::mt2203 _gen; +}; + +class gen_philox : public gen_base { +public: + explicit gen_philox() = delete; + gen_philox(sycl::queue queue, std::int64_t seed) : _gen(queue, seed) {} + engine_method get_engine_method() const override { + return engine_method::philox4x32x10; + } + void skip_ahead_gpu(std::int64_t nSkip) override { + skip_ahead(_gen, nSkip); + } + oneapi::mkl::rng::philox4x32x10* get() { + return &_gen; + } + +protected: + oneapi::mkl::rng::philox4x32x10 _gen; +}; + +class gen_mrg32k : public gen_base { +public: + explicit gen_mrg32k() = delete; + gen_mrg32k(sycl::queue queue, std::int64_t seed) : _gen(queue, seed) {} + engine_method get_engine_method() const override { + return engine_method::mrg32k3a; + } + void skip_ahead_gpu(std::int64_t nSkip) override { + skip_ahead(_gen, nSkip); + } + oneapi::mkl::rng::mrg32k3a* get() { + return &_gen; + } + +protected: + oneapi::mkl::rng::mrg32k3a _gen; +}; + +class gen_mt19937 : public gen_base { +public: + explicit gen_mt19937() = delete; + gen_mt19937(sycl::queue queue, std::int64_t seed) : _gen(queue, seed) {} + engine_method get_engine_method() const override { + return engine_method::mt19937; + } + void skip_ahead_gpu(std::int64_t nSkip) override { + skip_ahead(_gen, nSkip); + } + oneapi::mkl::rng::mt19937* get() { + return &_gen; + } + +protected: + oneapi::mkl::rng::mt19937 _gen; +}; + +class gen_mcg59 : public gen_base { +public: + explicit gen_mcg59() = delete; + gen_mcg59(sycl::queue queue, std::int64_t seed) : _gen(queue, seed) {} + engine_method get_engine_method() const override { + return engine_method::mcg59; + } + void skip_ahead_gpu(std::int64_t nSkip) override { + skip_ahead(_gen, nSkip); + } + oneapi::mkl::rng::mcg59* get() { + return &_gen; + } + +protected: + oneapi::mkl::rng::mcg59 _gen; +}; + +template +class id_to_mkl_engine {}; + +template <> +class id_to_mkl_engine { +public: + using engine_type = oneapi::mkl::rng::mt2203; +}; + +template <> +class id_to_mkl_engine { +public: + using engine_type = oneapi::mkl::rng::philox4x32x10; +}; + +template <> +class id_to_mkl_engine { +public: + using engine_type = oneapi::mkl::rng::mcg59; +}; + +template <> +class id_to_mkl_engine { +public: + using engine_type = oneapi::mkl::rng::mt19937; +}; + +template <> +class id_to_mkl_engine { +public: + using engine_type = oneapi::mkl::rng::mrg32k3a; +}; + +/// Helper classes that convert DAL base genetator to MKL generator + +template +class Helper {}; + +template <> +class Helper { + using mkl_engine = id_to_mkl_engine::engine_type; + +public: + mkl_engine* getter(gen_base* gen) { + return (dynamic_cast(gen))->get(); + } +}; + +template <> +class Helper { + using mkl_engine = id_to_mkl_engine::engine_type; + +public: + mkl_engine* getter(gen_base* gen) { + return (dynamic_cast(gen))->get(); + } +}; + +template <> +class Helper { + using mkl_engine = id_to_mkl_engine::engine_type; + +public: + mkl_engine* getter(gen_base* gen) { + return (dynamic_cast(gen))->get(); + } +}; + +template <> +class Helper { + using mkl_engine = id_to_mkl_engine::engine_type; + +public: + mkl_engine* getter(gen_base* gen) { + return (dynamic_cast(gen))->get(); + } +}; + +template <> +class Helper { + using mkl_engine = id_to_mkl_engine::engine_type; + +public: + mkl_engine* getter(gen_base* gen) { + return (dynamic_cast(gen))->get(); + } +}; + +/// A class that provides a unified interface for random number generation on both CPU and GPU devices. +/// +/// This class serves as a wrapper for random number generators (RNGs) that supports different engine types, +/// enabling efficient random number generation on heterogeneous platforms using SYCL. It integrates a host +/// (CPU) engine and a device (GPU) engine, allowing operations to be executed seamlessly on the appropriate +/// device. +/// +/// @tparam EngineType The RNG engine type to be used. Defaults to `engine_method::mt2203`. +/// +/// The class provides functionality to skip ahead in the RNG sequence, retrieve engine states, and +/// manage host and device engines independently. Support for `skip_ahead` on GPU is currently limited for +/// some engine types. +class dpc_engine { +public: + /// @param[in] queue The SYCL queue used to manage device operations. + /// @param[in] seed The initial seed for the random number generator. Defaults to `777`. + explicit dpc_engine(sycl::queue& queue, + std::int64_t seed = 777, + engine_method method = engine_method::mt2203) + : q(queue), + host_engine_(initialize_host_engine(seed, method)), + impl_(dynamic_cast( + host_engine_.get())) { + initialize_dpc_engine(queue, seed, method); + if (!impl_) { + throw std::domain_error("RNG engine is not supported"); + } + } + + dpc_engine& operator=(const dpc_engine& other); + + virtual ~dpc_engine() = default; + + void* get_host_engine_state() const { + return impl_->getState(); + } + + auto get_gpu_engine() { + return engine_; + } + + void skip_ahead_cpu(size_t nSkip) { + host_engine_->skipAhead(nSkip); + } + + void skip_ahead_gpu(size_t nSkip) { + engine_->skip_ahead_gpu(nSkip); + } + + sycl::queue& get_queue() { + return q; + } + +private: + daal::algorithms::engines::EnginePtr initialize_host_engine(std::int64_t seed, + engine_method method) { + switch (method) { + case engine_method::mt2203: + return daal::algorithms::engines::mt2203::Batch<>::create(seed); + case engine_method::mcg59: + return daal::algorithms::engines::mcg59::Batch<>::create(seed); + case engine_method::mrg32k3a: + return daal::algorithms::engines::mrg32k3a::Batch<>::create(seed); + case engine_method::philox4x32x10: + return daal::algorithms::engines::philox4x32x10::Batch<>::create(seed); + case engine_method::mt19937: + return daal::algorithms::engines::mt19937::Batch<>::create(seed); + default: throw std::invalid_argument("Unsupported engine type 2"); + } + } + + void initialize_dpc_engine(sycl::queue& queue, std::int64_t seed, engine_method method) { + switch (method) { + case engine_method::mt2203: engine_ = std::make_shared(queue, seed); break; + case engine_method::mcg59: engine_ = std::make_shared(queue, seed); break; + case engine_method::mrg32k3a: + engine_ = std::make_shared(queue, seed); + break; + case engine_method::philox4x32x10: + engine_ = std::make_shared(queue, seed); + break; + case engine_method::mt19937: + engine_ = std::make_shared(queue, seed); + break; + default: throw std::invalid_argument("Unsupported engine type 1"); + } + } + sycl::queue q; + daal::algorithms::engines::EnginePtr host_engine_; + std::shared_ptr engine_; + daal::algorithms::engines::internal::BatchBaseImpl* impl_; +}; + +template +void uniform(std::int64_t count, Type* dst, dpc_engine& engine_, Type a, Type b) { + if (sycl::get_pointer_type(dst, engine_.get_queue().get_context()) == + sycl::usm::alloc::device) { + throw domain_error(dal::detail::error_messages::unsupported_data_type()); + } + auto state = engine_.get_host_engine_state(); + uniform_dispatcher::uniform_by_cpu(count, dst, state, a, b); + engine_.skip_ahead_gpu(count); +} + +template +void uniform_without_replacement(std::int64_t count, + Type* dst, + Type* buffer, + dpc_engine& engine_, + Type a, + Type b) { + if (sycl::get_pointer_type(dst, engine_.get_queue().get_context()) == + sycl::usm::alloc::device) { + throw domain_error(dal::detail::error_messages::unsupported_data_type()); + } + void* state = engine_.get_host_engine_state(); + uniform_dispatcher::uniform_without_replacement_by_cpu(count, dst, buffer, state, a, b); + engine_.skip_ahead_gpu(count); +} + +template >> +void shuffle(std::int64_t count, Type* dst, dpc_engine& engine_) { + if (sycl::get_pointer_type(dst, engine_.get_queue().get_context()) == + sycl::usm::alloc::device) { + throw domain_error(dal::detail::error_messages::unsupported_data_type()); + } + Type idx[2]; + void* state = engine_.get_host_engine_state(); + for (std::int64_t i = 0; i < count; ++i) { + uniform_dispatcher::uniform_by_cpu(2, idx, state, 0, count); + std::swap(dst[idx[0]], dst[idx[1]]); + } + engine_.skip_ahead_gpu(count); +} + +template +void uniform(sycl::queue& queue, + std::int64_t count, + Type* dst, + dpc_engine& engine_, + Type a, + Type b, + const event_vector& deps = {}); + +template +void uniform_without_replacement(sycl::queue& queue, + std::int64_t count, + Type* dst, + Type* buffer, + dpc_engine& engine_, + Type a, + Type b, + const event_vector& deps = {}); + +template +void shuffle(sycl::queue& queue, + std::int64_t count, + Type* dst, + dpc_engine& engine_, + const event_vector& deps = {}); + +#endif + +} // namespace oneapi::dal::backend::primitives diff --git a/cpp/oneapi/dal/backend/primitives/rng/dpc_engine_collection.hpp b/cpp/oneapi/dal/backend/primitives/rng/dpc_engine_collection.hpp new file mode 100644 index 00000000000..35ba77a10df --- /dev/null +++ b/cpp/oneapi/dal/backend/primitives/rng/dpc_engine_collection.hpp @@ -0,0 +1,54 @@ +/******************************************************************************* +* 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. +*******************************************************************************/ + +#pragma once + +#include "oneapi/dal/backend/primitives/rng/rng_dpc.hpp" +#include "oneapi/dal/backend/primitives/ndarray.hpp" +#include + +#include "oneapi/dal/backend/primitives/rng/utils.hpp" +#include "oneapi/dal/backend/primitives/rng/rng_types.hpp" +#include "oneapi/dal/table/common.hpp" + +namespace oneapi::dal::backend::primitives { + +#ifdef ONEDAL_DATA_PARALLEL + +template +class engine_collection_oneapi { +public: + engine_collection_oneapi(sycl::queue& queue, std::int64_t count, std::int64_t seed = 777) + : count_(count), + base_seed_(seed) { + engines_.reserve(count_); + for (std::int64_t i = 0; i < count_; ++i) { + engines_.push_back(dpc_engine(queue, base_seed_ + i)); + } + } + + std::vector> get_engines() const { + return engines_; + } + +private: + std::int64_t count_; + std::int64_t base_seed_; + std::vector> engines_; +}; + +#endif +} // namespace oneapi::dal::backend::primitives diff --git a/cpp/oneapi/dal/backend/primitives/rng/dpc_engine_dpc.cpp b/cpp/oneapi/dal/backend/primitives/rng/dpc_engine_dpc.cpp new file mode 100644 index 00000000000..aa8c09ff329 --- /dev/null +++ b/cpp/oneapi/dal/backend/primitives/rng/dpc_engine_dpc.cpp @@ -0,0 +1,167 @@ +/******************************************************************************* +* 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/backend/primitives/rng/dpc_engine.hpp" +#include "oneapi/dal/backend/primitives/ndarray.hpp" + +#include + +namespace oneapi::dal::backend::primitives { + +namespace bk = oneapi::dal::backend; + +template +void uniform(sycl::queue& queue, + std::int64_t count, + Type* dst, + dpc_engine& engine_, + Type a, + Type b, + const event_vector& deps) { + if (sycl::get_pointer_type(dst, engine_.get_queue().get_context()) == sycl::usm::alloc::host) { + throw domain_error(dal::detail::error_messages::unsupported_data_type()); + } + oneapi::mkl::rng::uniform distr(a, b); + sycl::event event; + switch (engine_.get_gpu_engine()->get_engine_method()) { + case engine_method::mt2203: { + Helper helper; + event = oneapi::mkl::rng::generate(distr, + *(helper.getter(engine_.get_gpu_engine().get())), + count, + dst, + { deps }); + break; + } + case engine_method::mcg59: { + Helper helper; + event = oneapi::mkl::rng::generate(distr, + *(helper.getter(engine_.get_gpu_engine().get())), + count, + dst, + { deps }); + break; + } + case engine_method::mrg32k3a: { + Helper helper; + event = oneapi::mkl::rng::generate(distr, + *(helper.getter(engine_.get_gpu_engine().get())), + count, + dst, + { deps }); + break; + } + case engine_method::philox4x32x10: { + Helper helper; + event = oneapi::mkl::rng::generate(distr, + *(helper.getter(engine_.get_gpu_engine().get())), + count, + dst, + { deps }); + break; + } + case engine_method::mt19937: { + Helper helper; + event = oneapi::mkl::rng::generate(distr, + *(helper.getter(engine_.get_gpu_engine().get())), + count, + dst, + { deps }); + break; + } + default: throw std::invalid_argument("Unsupported engine type 3"); + } + event.wait_and_throw(); + engine_.skip_ahead_cpu(count); +} + +//Currently only CPU impl +template +void uniform_without_replacement(sycl::queue& queue, + std::int64_t count, + Type* dst, + Type* buffer, + dpc_engine& engine_, + Type a, + Type b, + const event_vector& deps) { + if (sycl::get_pointer_type(dst, engine_.get_queue().get_context()) == + sycl::usm::alloc::device) { + throw domain_error(dal::detail::error_messages::unsupported_data_type()); + } + void* state = engine_.get_host_engine_state(); + engine_.skip_ahead_gpu(count); + uniform_dispatcher::uniform_without_replacement_by_cpu(count, dst, buffer, state, a, b); +} + +//Currently only CPU impl +template +void shuffle(sycl::queue& queue, + std::int64_t count, + Type* dst, + dpc_engine& engine_, + const event_vector& deps) { + Type idx[2]; + if (sycl::get_pointer_type(dst, engine_.get_queue().get_context()) == + sycl::usm::alloc::device) { + throw domain_error(dal::detail::error_messages::unsupported_data_type()); + } + void* state = engine_.get_host_engine_state(); + engine_.skip_ahead_gpu(count); + + for (std::int64_t i = 0; i < count; ++i) { + uniform_dispatcher::uniform_by_cpu(2, idx, state, 0, count); + std::swap(dst[idx[0]], dst[idx[1]]); + } +} + +#define INSTANTIATE_UNIFORM(F) \ + template ONEDAL_EXPORT void uniform(sycl::queue& queue, \ + std::int64_t count_, \ + F* dst, \ + dpc_engine& engine_, \ + F a, \ + F b, \ + const event_vector& deps); + +INSTANTIATE_UNIFORM(float) +INSTANTIATE_UNIFORM(double) +INSTANTIATE_UNIFORM(std::int32_t) + +#define INSTANTIATE_UWR(F) \ + template ONEDAL_EXPORT void uniform_without_replacement(sycl::queue& queue, \ + std::int64_t count_, \ + F* dst, \ + F* buff, \ + dpc_engine& engine_, \ + F a, \ + F b, \ + const event_vector& deps); + +INSTANTIATE_UWR(float) +INSTANTIATE_UWR(double) +INSTANTIATE_UWR(std::int32_t) + +#define INSTANTIATE_SHUFFLE(F) \ + template ONEDAL_EXPORT void shuffle(sycl::queue& queue, \ + std::int64_t count_, \ + F* dst, \ + dpc_engine& engine_, \ + const event_vector& deps); + +INSTANTIATE_SHUFFLE(std::int32_t) + +} // namespace oneapi::dal::backend::primitives diff --git a/cpp/oneapi/dal/backend/primitives/rng/host_engine.hpp b/cpp/oneapi/dal/backend/primitives/rng/host_engine.hpp new file mode 100644 index 00000000000..f01ffa8fffc --- /dev/null +++ b/cpp/oneapi/dal/backend/primitives/rng/host_engine.hpp @@ -0,0 +1,124 @@ +/******************************************************************************* +* Copyright 2021 Intel Corporation +* +* 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. +*******************************************************************************/ + +#pragma once + +#include +#include +#include +#include +#include + +#include "oneapi/dal/backend/primitives/rng/utils.hpp" +#include "oneapi/dal/backend/primitives/rng/rng_types.hpp" + +namespace oneapi::dal::backend::primitives { + +/// A class that provides an interface for random number generation on the host (CPU) only. +/// +/// This class serves as a wrapper for host-based random number generators (RNGs), supporting multiple engine +/// types for flexible and efficient random number generation on CPU. It abstracts the underlying engine +/// implementation and provides an interface to manage and retrieve the engine's state. +/// +/// @tparam EngineType The RNG engine type to be used. Defaults to `engine_method::mt2203`. +/// +/// @param[in] seed The initial seed for the random number generator. Defaults to `777`. +/// +/// @note The class only supports host-based RNG and does not require a SYCL queue or device context. +class host_engine { +public: + explicit host_engine(std::int64_t seed = 777, engine_method method = engine_method::mt2203) + : host_engine_(initialize_host_engine(seed, method)), + impl_(dynamic_cast( + host_engine_.get())) { + if (!impl_) { + throw std::domain_error("RNG engine is not supported"); + } + } + + explicit host_engine(const daal::algorithms::engines::EnginePtr& eng) : host_engine_(eng) { + impl_ = dynamic_cast(eng.get()); + if (!impl_) { + throw domain_error(dal::detail::error_messages::rng_engine_is_not_supported()); + } + } + + host_engine& operator=(const daal::algorithms::engines::EnginePtr& eng) { + host_engine_ = eng; + impl_ = dynamic_cast(eng.get()); + if (!impl_) { + throw domain_error(dal::detail::error_messages::rng_engine_is_not_supported()); + } + + return *this; + } + + virtual ~host_engine() = default; + + void* get_host_engine_state() const { + return impl_->getState(); + } + +private: + daal::algorithms::engines::EnginePtr initialize_host_engine(std::int64_t seed, + engine_method method) { + switch (method) { + case engine_method::mt2203: + return daal::algorithms::engines::mt2203::Batch<>::create(seed); + case engine_method::mcg59: + return daal::algorithms::engines::mcg59::Batch<>::create(seed); + case engine_method::mrg32k3a: + return daal::algorithms::engines::mrg32k3a::Batch<>::create(seed); + case engine_method::philox4x32x10: + return daal::algorithms::engines::philox4x32x10::Batch<>::create(seed); + case engine_method::mt19937: + return daal::algorithms::engines::mt19937::Batch<>::create(seed); + default: throw std::invalid_argument("Unsupported engine type 0"); + } + } + + daal::algorithms::engines::EnginePtr host_engine_; + daal::algorithms::engines::internal::BatchBaseImpl* impl_; +}; + +template +void uniform(std::int64_t count, Type* dst, host_engine& host_engine, Type a, Type b) { + auto state = host_engine.get_host_engine_state(); + uniform_dispatcher::uniform_by_cpu(count, dst, state, a, b); +} + +template +void uniform_without_replacement(std::int64_t count, + Type* dst, + Type* buffer, + host_engine host_engine, + Type a, + Type b) { + auto state = host_engine.get_host_engine_state(); + uniform_dispatcher::uniform_without_replacement_by_cpu(count, dst, buffer, state, a, b); +} + +template >> +void shuffle(std::int64_t count, Type* dst, host_engine host_engine) { + auto state = host_engine.get_host_engine_state(); + Type idx[2]; + for (std::int64_t i = 0; i < count; ++i) { + uniform_dispatcher::uniform_by_cpu(2, idx, state, 0, count); + std::swap(dst[idx[0]], dst[idx[1]]); + } +} + +} // namespace oneapi::dal::backend::primitives diff --git a/cpp/oneapi/dal/backend/primitives/rng/rng_engine_collection.hpp b/cpp/oneapi/dal/backend/primitives/rng/host_engine_collection.hpp similarity index 66% rename from cpp/oneapi/dal/backend/primitives/rng/rng_engine_collection.hpp rename to cpp/oneapi/dal/backend/primitives/rng/host_engine_collection.hpp index 09a5a589141..1bcfe7493c5 100644 --- a/cpp/oneapi/dal/backend/primitives/rng/rng_engine_collection.hpp +++ b/cpp/oneapi/dal/backend/primitives/rng/host_engine_collection.hpp @@ -16,26 +16,27 @@ #pragma once -#include "oneapi/dal/backend/primitives/rng/rng_engine.hpp" +#include "oneapi/dal/backend/primitives/rng/host_engine.hpp" #include namespace oneapi::dal::backend::primitives { -template class engine_collection { public: - explicit engine_collection(Size count, std::int64_t seed = 777) + explicit engine_collection(std::int64_t count, + std::int64_t seed = 777, + engine_method method = engine_method::mt2203) : count_(count), - engine_(daal::algorithms::engines::mt2203::Batch<>::create(seed)), + engine_(initialize_host_engine(seed, method)), params_(count), technique_(daal::algorithms::engines::internal::family), daal_engine_list_(count) {} template - std::vector operator()(Op&& op) { + std::vector operator()(Op&& op) { daal::services::Status status; - for (Size i = 0; i < count_; ++i) { + for (std::int64_t i = 0; i < count_; ++i) { op(i, params_.nSkip[i]); } select_parallelization_technique(technique_); @@ -49,8 +50,8 @@ class engine_collection { dal::backend::interop::status_to_exception(status); } - std::vector engine_list(count_); - for (Size i = 0; i < count_; ++i) { + std::vector engine_list(count_); + for (std::int64_t i = 0; i < count_; ++i) { engine_list[i] = daal_engine_list_[i]; } @@ -59,6 +60,23 @@ class engine_collection { } private: + daal::algorithms::engines::EnginePtr initialize_host_engine(std::int64_t seed, + engine_method method) { + switch (method) { + case engine_method::mt2203: + return daal::algorithms::engines::mt2203::Batch<>::create(seed); + case engine_method::mcg59: + return daal::algorithms::engines::mcg59::Batch<>::create(seed); + case engine_method::mrg32k3a: + return daal::algorithms::engines::mrg32k3a::Batch<>::create(seed); + case engine_method::philox4x32x10: + return daal::algorithms::engines::philox4x32x10::Batch<>::create(seed); + case engine_method::mt19937: + return daal::algorithms::engines::mt19937::Batch<>::create(seed); + default: throw std::invalid_argument("Unsupported engine type"); + } + } + void select_parallelization_technique( daal::algorithms::engines::internal::ParallelizationTechnique& technique) { auto daal_engine_impl = @@ -82,7 +100,7 @@ class engine_collection { } private: - Size count_; + std::int64_t count_; daal::algorithms::engines::EnginePtr engine_; daal::algorithms::engines::internal::Params params_; daal::algorithms::engines::internal::ParallelizationTechnique technique_; diff --git a/cpp/oneapi/dal/backend/primitives/rng/rng_engine.hpp b/cpp/oneapi/dal/backend/primitives/rng/rng_engine.hpp deleted file mode 100644 index c8ca3b13ce9..00000000000 --- a/cpp/oneapi/dal/backend/primitives/rng/rng_engine.hpp +++ /dev/null @@ -1,101 +0,0 @@ -/******************************************************************************* -* Copyright 2021 Intel Corporation -* -* 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. -*******************************************************************************/ - -#pragma once - -#include - -#include "oneapi/dal/backend/primitives/rng/utils.hpp" - -namespace oneapi::dal::backend::primitives { - -template -class rng { -public: - rng() = default; - ~rng() = default; - - void uniform(Size count, Type* dst, void* state, Type a, Type b) { - uniform_dispatcher::uniform_by_cpu(count, dst, state, a, b); - } - - void uniform_without_replacement(Size count, - Type* dst, - Type* buffer, - void* state, - Type a, - Type b) { - uniform_dispatcher::uniform_without_replacement_by_cpu(count, - dst, - buffer, - state, - a, - b); - } - - template >> - void shuffle(Size count, Type* dst, void* state) { - Type idx[2]; - - for (Size i = 0; i < count; ++i) { - uniform_dispatcher::uniform_by_cpu(2, idx, state, 0, count); - std::swap(dst[idx[0]], dst[idx[1]]); - } - } - -private: - daal::internal::RNGsInst daal_rng_; -}; - -class engine { -public: - explicit engine(std::int64_t seed = 777) - : engine_(daal::algorithms::engines::mt2203::Batch<>::create(seed)) { - impl_ = dynamic_cast(engine_.get()); - if (!impl_) { - throw domain_error(dal::detail::error_messages::rng_engine_is_not_supported()); - } - } - - explicit engine(const daal::algorithms::engines::EnginePtr& eng) : engine_(eng) { - impl_ = dynamic_cast(eng.get()); - if (!impl_) { - throw domain_error(dal::detail::error_messages::rng_engine_is_not_supported()); - } - } - - virtual ~engine() = default; - - engine& operator=(const daal::algorithms::engines::EnginePtr& eng) { - engine_ = eng; - impl_ = dynamic_cast(eng.get()); - if (!impl_) { - throw domain_error(dal::detail::error_messages::rng_engine_is_not_supported()); - } - - return *this; - } - - void* get_state() const { - return impl_->getState(); - } - -private: - daal::algorithms::engines::EnginePtr engine_; - daal::algorithms::engines::internal::BatchBaseImpl* impl_; -}; - -} // namespace oneapi::dal::backend::primitives diff --git a/cpp/oneapi/dal/backend/primitives/rng/rng_types.hpp b/cpp/oneapi/dal/backend/primitives/rng/rng_types.hpp new file mode 100644 index 00000000000..c8703ae8165 --- /dev/null +++ b/cpp/oneapi/dal/backend/primitives/rng/rng_types.hpp @@ -0,0 +1,34 @@ +/******************************************************************************* +* 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. +*******************************************************************************/ + +#pragma once + +namespace oneapi::dal::backend::primitives { + +/// Enum class representing different random number generation (RNG) engine methods. +/// +/// This enumeration defines the available RNG engines supported by the library. +/// Each engine method corresponds to a specific algorithm for generating random numbers +/// @enum engine_method +/// Enumeration of RNG engine methods: +/// - `mt2203`: Mersenne Twister engine with specific optimizations for parallel environments. +/// - `mcg59`: Multiplicative congruential generator with a modulus of \(2^{59}\). +/// - `mt19937`: Standard Mersenne Twister engine with a period of \(2^{19937} - 1\). +/// - `mrg32k3a`: Combined multiple recursive generator with a period of \(2^{191}\). +/// - `philox4x32x10`: Counter-based RNG engine optimized for parallel computations. +enum class engine_method { mt2203, mcg59, mt19937, mrg32k3a, philox4x32x10 }; + +} // namespace oneapi::dal::backend::primitives diff --git a/cpp/oneapi/dal/backend/primitives/rng/test/rng_dpc.cpp b/cpp/oneapi/dal/backend/primitives/rng/test/rng_dpc.cpp new file mode 100644 index 00000000000..8d544415b4b --- /dev/null +++ b/cpp/oneapi/dal/backend/primitives/rng/test/rng_dpc.cpp @@ -0,0 +1,211 @@ +/******************************************************************************* +* 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/test/engine/common.hpp" +#include "oneapi/dal/test/engine/fixtures.hpp" +#include "oneapi/dal/test/engine/dataframe.hpp" + +#include "oneapi/dal/backend/primitives/rng/dpc_engine.hpp" +#include "oneapi/dal/backend/primitives/rng/host_engine.hpp" +#include "oneapi/dal/backend/primitives/rng/rng_types.hpp" +#include "oneapi/dal/backend/primitives/ndarray.hpp" +#include + +#include "oneapi/dal/backend/primitives/rng/utils.hpp" +#include "oneapi/dal/table/common.hpp" + +namespace oneapi::dal::backend::primitives::test { + +namespace te = dal::test::engine; + +class mt2203 {}; +class mcg59 {}; +class mrg32k3a {}; +class mt19937 {}; +class philox4x32x10 {}; + +template +struct engine_map {}; + +template <> +struct engine_map { + constexpr static auto value = engine_method::mt2203; +}; + +template <> +struct engine_map { + constexpr static auto value = engine_method::mcg59; +}; + +template <> +struct engine_map { + constexpr static auto value = engine_method::mrg32k3a; +}; + +template <> +struct engine_map { + constexpr static auto value = engine_method::philox4x32x10; +}; + +template <> +struct engine_map { + constexpr static auto value = engine_method::mt19937; +}; + +template +constexpr auto engine_v = engine_map::value; + +template +class rng_test : public te::float_algo_fixture> { +public: + using DataType = std::tuple_element_t<0, TestType>; + using EngineType = std::tuple_element_t<1, TestType>; + static constexpr auto engine_test_type = engine_v; + + auto get_host_engine(std::int64_t seed) { + auto rng_engine = host_engine(seed, engine_test_type); + return rng_engine; + } + + auto get_dpc_engine(std::int64_t seed) { + auto rng_engine = dpc_engine(this->get_queue(), seed, engine_test_type); + return rng_engine; + } + + auto allocate_array_host(std::int64_t elem_count) { + auto arr_host = ndarray::empty({ elem_count }); + return arr_host; + } + + auto allocate_array_device(std::int64_t elem_count) { + auto& q = this->get_queue(); + auto arr_gpu = ndarray::empty(q, { elem_count }, sycl::usm::alloc::device); + return arr_gpu; + } + + void check_results(const ndarray& arr_1, const ndarray& arr_2) { + const auto arr_1_host = arr_1.to_host(this->get_queue()); + const DataType* val_arr_1_host_ptr = arr_1_host.get_data(); + + const auto arr_2_host = arr_2.to_host(this->get_queue()); + const DataType* val_arr_2_host_ptr = arr_2_host.get_data(); + + for (std::int64_t el = 0; el < arr_2_host.get_count(); el++) { + // Due to MKL inside generates floats on GPU and doubles on CPU, it makes sense to add minor eps. + REQUIRE(abs(val_arr_1_host_ptr[el] - val_arr_2_host_ptr[el]) < 0.1); + } + } +}; + +using rng_types = COMBINE_TYPES((float, double), (mt2203, mt19937, mcg59, mrg32k3a, philox4x32x10)); + +TEMPLATE_LIST_TEST_M(rng_test, "rng cpu vs gpu", "[rng]", rng_types) { + SKIP_IF(this->get_policy().is_cpu()); + SKIP_IF(this->not_float64_friendly()); + using Float = std::tuple_element_t<0, TestType>; + + std::int64_t elem_count = GENERATE_COPY(10, 777, 10000, 50000); + std::int64_t seed = GENERATE_COPY(777, 999); + + auto arr_gpu = this->allocate_array_device(elem_count); + auto arr_host = this->allocate_array_host(elem_count); + auto arr_gpu_ptr = arr_gpu.get_mutable_data(); + auto arr_host_ptr = arr_host.get_mutable_data(); + + auto rng_engine = this->get_dpc_engine(seed); + auto rng_engine_ = this->get_dpc_engine(seed); + + uniform(elem_count, arr_host_ptr, rng_engine, 0, elem_count); + uniform(this->get_queue(), elem_count, arr_gpu_ptr, rng_engine_, 0, elem_count); + + this->check_results(arr_gpu, arr_host); +} + +using rng_types_skip_ahead_support = COMBINE_TYPES((float, double), + (mt19937, mcg59, mrg32k3a, philox4x32x10)); + +TEMPLATE_LIST_TEST_M(rng_test, "mixed rng cpu skip", "[rng]", rng_types_skip_ahead_support) { + SKIP_IF(this->get_policy().is_cpu()); + SKIP_IF(this->not_float64_friendly()); + using Float = std::tuple_element_t<0, TestType>; + + std::int64_t elem_count = GENERATE_COPY(10, 777, 10000, 100000); + std::int64_t seed = GENERATE_COPY(777, 999); + + auto arr_host_init_1 = this->allocate_array_host(elem_count); + auto arr_host_init_2 = this->allocate_array_host(elem_count); + + auto arr_gpu = this->allocate_array_device(elem_count); + auto arr_host = this->allocate_array_host(elem_count); + + auto arr_host_init_1_ptr = arr_host_init_1.get_mutable_data(); + auto arr_host_init_2_ptr = arr_host_init_2.get_mutable_data(); + auto arr_gpu_ptr = arr_gpu.get_mutable_data(); + auto arr_host_ptr = arr_host.get_mutable_data(); + + auto rng_engine = this->get_dpc_engine(seed); + auto rng_engine_2 = this->get_dpc_engine(seed); + + uniform(elem_count, arr_host_init_1_ptr, rng_engine, 0, elem_count); + uniform(elem_count, arr_host_init_2_ptr, rng_engine_2, 0, elem_count); + + uniform(this->get_queue(), elem_count, arr_gpu_ptr, rng_engine, 0, elem_count); + uniform(elem_count, arr_host_ptr, rng_engine_2, 0, elem_count); + + this->check_results(arr_host_init_1, arr_host_init_2); + this->check_results(arr_gpu, arr_host); +} + +TEMPLATE_LIST_TEST_M(rng_test, "mixed rng gpu skip", "[rng]", rng_types_skip_ahead_support) { + SKIP_IF(this->get_policy().is_cpu()); + SKIP_IF(this->not_float64_friendly()); + using Float = std::tuple_element_t<0, TestType>; + + std::int64_t elem_count = GENERATE_COPY(10, 100, 777, 10000); + std::int64_t seed = GENERATE_COPY(1, 777, 999); + + auto arr_device_init_1 = this->allocate_array_device(elem_count); + auto arr_device_init_2 = this->allocate_array_device(elem_count); + + auto arr_gpu = this->allocate_array_device(elem_count); + auto arr_host = this->allocate_array_host(elem_count); + + auto arr_device_init_1_ptr = arr_device_init_1.get_mutable_data(); + auto arr_device_init_2_ptr = arr_device_init_2.get_mutable_data(); + auto arr_gpu_ptr = arr_gpu.get_mutable_data(); + auto arr_host_ptr = arr_host.get_mutable_data(); + + auto rng_engine = this->get_dpc_engine(seed); + auto rng_engine_2 = this->get_dpc_engine(seed); + + uniform(this->get_queue(), elem_count, arr_device_init_1_ptr, rng_engine, 0, elem_count); + uniform(this->get_queue(), + elem_count, + arr_device_init_2_ptr, + rng_engine_2, + 0, + elem_count); + + uniform(this->get_queue(), elem_count, arr_gpu_ptr, rng_engine, 0, elem_count); + uniform(elem_count, arr_host_ptr, rng_engine_2, 0, elem_count); + + this->check_results(arr_device_init_1, arr_device_init_2); + this->check_results(arr_gpu, arr_host); +} + +//TODO: add engine collection test + separate host_engine tests + +} // namespace oneapi::dal::backend::primitives::test diff --git a/examples/oneapi/dpc/source/decision_forest/df_cls_hist_batch.cpp b/examples/oneapi/dpc/source/decision_forest/df_cls_hist_batch.cpp index 4900ea6fd54..7672ed209f2 100644 --- a/examples/oneapi/dpc/source/decision_forest/df_cls_hist_batch.cpp +++ b/examples/oneapi/dpc/source/decision_forest/df_cls_hist_batch.cpp @@ -47,6 +47,7 @@ void run(sycl::queue& q) { .set_features_per_node(x_train.get_column_count()) .set_min_observations_in_leaf_node(8) .set_min_observations_in_split_node(16) + .set_engine_method(df::df_engine_types::philox4x32x10) .set_min_weight_fraction_in_leaf_node(0.0) .set_min_impurity_decrease_in_split_node(0.0) .set_error_metric_mode(df::error_metric_mode::out_of_bag_error) diff --git a/makefile.lst b/makefile.lst index 92dc52ff521..b042ede80a7 100755 --- a/makefile.lst +++ b/makefile.lst @@ -65,7 +65,7 @@ multiclassclassifier += classifier k_nearest_neighbors += engines classifier logistic_regression += classifier optimization_solver objective_function engines implicit_als += engines distributions -engines += engines/mt19937 engines/mcg59 engines/mt2203 +engines += engines/mt19937 engines/mcg59 engines/mrg32k3a engines/philox4x32x10 engines/mt2203 distributions += distributions/bernoulli distributions/normal distributions/uniform tsne += @@ -95,6 +95,8 @@ CORE.ALGORITHMS.FULL := \ elastic_net \ engines \ engines/mcg59 \ + engines/mrg32k3a \ + engines/philox4x32x10 \ engines/mt19937 \ engines/mt2203 \ em \ @@ -309,6 +311,8 @@ JJ.ALGORITHMS := adaboost elastic_net/prediction \ engines \ engines/mcg59 \ + engines/mrg32k3a \ + engines/philox4x32x10 \ engines/mt19937 \ engines/mt2203 \ em_gmm \