From 6219dc86b486a240dc7c8ce0ebdbc7069a5e9b3c Mon Sep 17 00:00:00 2001 From: Ekaterina Mekhnetsova Date: Thu, 18 Nov 2021 19:56:17 +0300 Subject: [PATCH] Cherry-pick doc commits for the release (#1999) --- cpp/oneapi/dal/algo/dbscan/common.hpp | 2 +- cpp/oneapi/dal/algo/dbscan/compute_types.hpp | 4 +- .../api/algorithms/clustering/dbscan.rst | 96 ++++++++++++++++++ .../api/algorithms/clustering/index.rst | 1 + docs/source/api/index.rst | 1 + docs/source/api/spmd/communicator.rst | 84 +++++++++++++++ docs/source/api/spmd/index.rst | 26 +++++ docs/source/api/spmd/overview.rst | 59 +++++++++++ docs/source/conf.py | 12 +++ .../includes/clustering/dbscan-examples.rst | 35 +++++++ .../clustering/dbscan-introduction.rst | 31 ++++++ .../clustering/dbscan-usage-examples.rst | 32 ++++++ .../includes/spmd/ccl-comm-usage-example.rst | 46 +++++++++ .../includes/spmd/mpi-comm-usage-example.rst | 46 +++++++++ docs/source/oneapi-interfaces.rst | 1 + .../onedal/algorithms/clustering/dbscan.rst | 73 +++++++++++++ .../onedal/algorithms/clustering/index.rst | 5 + .../algorithms/ensembles/decision-forest.rst | 7 ++ .../statistics/basic-statistics.rst | 6 ++ docs/source/onedal/glossary.rst | 20 ++++ docs/source/onedal/spmd/_static/spmd_flow.png | Bin 0 -> 23601 bytes docs/source/onedal/spmd/index.rst | 72 +++++++++++++ 22 files changed, 656 insertions(+), 3 deletions(-) create mode 100644 docs/source/api/algorithms/clustering/dbscan.rst create mode 100644 docs/source/api/spmd/communicator.rst create mode 100644 docs/source/api/spmd/index.rst create mode 100644 docs/source/api/spmd/overview.rst create mode 100644 docs/source/includes/clustering/dbscan-examples.rst create mode 100644 docs/source/includes/clustering/dbscan-introduction.rst create mode 100644 docs/source/includes/clustering/dbscan-usage-examples.rst create mode 100644 docs/source/includes/spmd/ccl-comm-usage-example.rst create mode 100644 docs/source/includes/spmd/mpi-comm-usage-example.rst create mode 100644 docs/source/onedal/algorithms/clustering/dbscan.rst create mode 100755 docs/source/onedal/spmd/_static/spmd_flow.png create mode 100644 docs/source/onedal/spmd/index.rst diff --git a/cpp/oneapi/dal/algo/dbscan/common.hpp b/cpp/oneapi/dal/algo/dbscan/common.hpp index d688419761c..3566779b9c3 100644 --- a/cpp/oneapi/dal/algo/dbscan/common.hpp +++ b/cpp/oneapi/dal/algo/dbscan/common.hpp @@ -155,7 +155,7 @@ class descriptor : public detail::descriptor_base { using method_t = Method; using task_t = Task; - /// Creates a new instance of the class with the given :literals:`epsilon`, `min_observations` + /// Creates a new instance of the class with the given :literal:`epsilon`, :literal:`min_observations` explicit descriptor(double epsilon, std::int64_t min_observations) { set_min_observations(min_observations); set_epsilon(epsilon); diff --git a/cpp/oneapi/dal/algo/dbscan/compute_types.hpp b/cpp/oneapi/dal/algo/dbscan/compute_types.hpp index 757696e86d1..2954b4e56c4 100644 --- a/cpp/oneapi/dal/algo/dbscan/compute_types.hpp +++ b/cpp/oneapi/dal/algo/dbscan/compute_types.hpp @@ -116,7 +116,7 @@ class compute_result { } /// An $m \\times 1$ table with the indices of core observations in - /// the input data. $m is a number of core observations + /// the input data. $m$ is a number of core observations const table& get_core_observation_indices() const; auto& set_core_observation_indices(const table& value) { @@ -125,7 +125,7 @@ class compute_result { } /// An $m \\times p$ table with the core observations in - /// the input data. $m is a number of core observations + /// the input data. $m$ is a number of core observations const table& get_core_observations() const; auto& set_core_observations(const table& value) { diff --git a/docs/source/api/algorithms/clustering/dbscan.rst b/docs/source/api/algorithms/clustering/dbscan.rst new file mode 100644 index 00000000000..9cd02d20698 --- /dev/null +++ b/docs/source/api/algorithms/clustering/dbscan.rst @@ -0,0 +1,96 @@ +.. ****************************************************************************** +.. * 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. +.. *******************************************************************************/ + +.. highlight:: cpp +.. default-domain:: cpp + +.. _api_dbscan: + +====== +DBSCAN +====== + +.. include:: ../../../includes/clustering/dbscan-introduction.rst + +------------------------ +Mathematical formulation +------------------------ + +Refer to :ref:`Developer Guide: DBSCAN `. + +--------------------- +Programming Interface +--------------------- + +All types and functions in this section are declared in the +``oneapi::dal::dbscan`` namespace and are available via inclusion of the +``oneapi/dal/algo/dbscan.hpp`` header file. + +Descriptor +---------- +.. onedal_class:: oneapi::dal::dbscan::descriptor + +Method tags +~~~~~~~~~~~ +.. onedal_tags_namespace:: oneapi::dal::dbscan::method + +Task tags +~~~~~~~~~ +.. onedal_tags_namespace:: oneapi::dal::dbscan::task + + +.. _dbscan_c_api: + +Computation :cpp:expr:`compute(...)` +------------------------------------ + +.. _dbscan_c_api_input: + +Input +~~~~~ +.. onedal_class:: oneapi::dal::dbscan::compute_input + +.. _dbscan_c_api_result: + +Result +~~~~~~ +.. onedal_class:: oneapi::dal::dbscan::compute_result + +Operation +~~~~~~~~~ + +.. function:: template \ + dbscan::compute_result compute(const Descriptor& desc, \ + const dbscan::compute_input& input) + + :param desc: DBSCAN algorithm descriptor :expr:`dbscan::descriptor` + :param input: Input data for the compute operation + + Preconditions + | :expr:`input.data.has_data == true` + | :expr:`!input.weights.has_data || input.weights.row_count == input.data.row_count && input.weights.column_count == 1` + +------------- +Usage example +------------- + +.. include:: ../../../includes/clustering/dbscan-usage-examples.rst + +-------- +Examples +-------- + +.. include:: ../../../includes/clustering/dbscan-examples.rst diff --git a/docs/source/api/algorithms/clustering/index.rst b/docs/source/api/algorithms/clustering/index.rst index ef966d80373..c09bd00c387 100644 --- a/docs/source/api/algorithms/clustering/index.rst +++ b/docs/source/api/algorithms/clustering/index.rst @@ -23,5 +23,6 @@ This chapter describes programming interfaces of the clustering algorithms imple .. toctree:: :titlesonly: + dbscan.rst kmeans.rst kmeans-init.rst diff --git a/docs/source/api/index.rst b/docs/source/api/index.rst index 44e7c916639..62792b4f032 100644 --- a/docs/source/api/index.rst +++ b/docs/source/api/index.rst @@ -23,4 +23,5 @@ C++ API data-management/index.rst algorithms/index.rst + spmd/index.rst diff --git a/docs/source/api/spmd/communicator.rst b/docs/source/api/spmd/communicator.rst new file mode 100644 index 00000000000..64d9a96656d --- /dev/null +++ b/docs/source/api/spmd/communicator.rst @@ -0,0 +1,84 @@ +.. ****************************************************************************** +.. * 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. +.. *******************************************************************************/ + +.. highlight:: cpp + +.. _api_communicator: + +============= +Communicators +============= + +.. _communicator_programming_interface: + +--------------------- +Programming interface +--------------------- + +All types and functions in this section are declared in the +``oneapi::dal::spmd::preview`` namespace and are available via inclusion of the +header file from specified backend. + +Communicator +------------ + +A base implementation of the :term:`communicator` concept. +The :term:`communicator` type and all of its subtypes are :term:`reference-counted `: + +1. The instance stores a pointer to the communicator implementation that holds all + property values and data. + +2. The reference count indicates how many communicator objects refer to the same implementation. + +3. The communicator increments the reference count + for it to be equal to the number of communicator objects sharing the same implementation. + +4. The communicator decrements the reference count when the + communicator goes out of the scope. If the reference count is zero, the communicator + frees its implementation. + +USM and non-USM memory usage +---------------------------- + +There are two types of memory access: + +- USM memory access (both USM and non-USM pointers can be used) +- Host, or non-USM, memory access (only non-USM pointers can be used) + +Use one of the following tags to select a memory access type: + +device_memory_access::none + Assumes only non-USM pointers are used for a collective operation. + +device_memory_access::usm + Both USM and non-USM can be used. Pointer type is controlled by + the use of ``sycl::queue`` object as a first parameter for collective + operations. The use of ``sycl::queue`` object is obligatory for USM + pointers. + +Request +------- + +Request is an object to control asynchronous communication. + +Reducion operations +------------------- + +The following reduction operations are supported: + +- Max +- Min +- Sum diff --git a/docs/source/api/spmd/index.rst b/docs/source/api/spmd/index.rst new file mode 100644 index 00000000000..f74833382fe --- /dev/null +++ b/docs/source/api/spmd/index.rst @@ -0,0 +1,26 @@ +.. ****************************************************************************** +.. * 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. +.. *******************************************************************************/ + +=============================================== +Distributed Model: Single Process Multiple Data +=============================================== + +Refer to :ref:`Developer Guide: SPMD distributed model `. + +.. toctree:: + + overview.rst + communicator.rst diff --git a/docs/source/api/spmd/overview.rst b/docs/source/api/spmd/overview.rst new file mode 100644 index 00000000000..d20163a5133 --- /dev/null +++ b/docs/source/api/spmd/overview.rst @@ -0,0 +1,59 @@ +.. ****************************************************************************** +.. * 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. +.. *******************************************************************************/ + +.. highlight:: cpp +.. default-domain:: cpp + +.. _api_spmd: + +====================== +Distributed SPMD model +====================== + +Refer to :ref:`Developer Guide: SPMD `. + +--------------------- +Programming interface +--------------------- + +All types and functions in this section are declared in the +``oneapi::dal::spmd::preview`` namespace and are available via inclusion of the +header file from specified backend. + +:term:`SPMD` distributed model consists of the following components: + +1. Additional ``train``, ``infer``, and ``compute`` methods that accept ``communicator`` object + as the first parameter. Those methods are expected to be called on all ranks to start + distributed simulations. + +2. The :term:`communicator` class that contains methods to perform collective operations among all ranks. + +3. Free functions to create a :term:`communicator` using a specified :term:`communicator backend`. Available backends are ``ccl`` + and ``mpi``. + +------------- +Usage example +------------- + +The following listings provide a brief introduction on how to create a particular communicator. + +.. rubric:: MPI backend + +.. include:: ../../includes/spmd/mpi-comm-usage-example.rst + +.. rubric:: CCL backend + +.. include:: ../../includes/spmd/ccl-comm-usage-example.rst diff --git a/docs/source/conf.py b/docs/source/conf.py index b6128ade77e..0c22fdd7c2d 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -281,6 +281,18 @@ ('cpp:identifier', 'oneapi::dal::basic_statistics::method'), ('cpp:identifier', 'oneapi::dal::basic_statistics::method::v1'), ('cpp:identifier', 'oneapi::dal::basic_statistics::method::v1::dense'), + # dbscan + ('cpp:identifier', 'dbscan'), + ('cpp:identifier', 'dbscan::descriptor'), + ('cpp:identifier', 'dbscan::compute_result'), + ('cpp:identifier', 'dbscan::compute_input'), + ('cpp:identifier', 'oneapi::dal::dbscan'), + ('cpp:identifier', 'oneapi::dal::dbscan::task'), + ('cpp:identifier', 'oneapi::dal::dbscan::task::v1'), + ('cpp:identifier', 'oneapi::dal::dbscan::task::v1::compute'), + ('cpp:identifier', 'oneapi::dal::dbscan::method'), + ('cpp:identifier', 'oneapi::dal::dbscan::method::v1'), + ('cpp:identifier', 'oneapi::dal::dbscan::method::v1::brute_force'), # common for algorithms ('cpp:identifier', 'result'), # common for result options diff --git a/docs/source/includes/clustering/dbscan-examples.rst b/docs/source/includes/clustering/dbscan-examples.rst new file mode 100644 index 00000000000..e0a1d7c5837 --- /dev/null +++ b/docs/source/includes/clustering/dbscan-examples.rst @@ -0,0 +1,35 @@ +.. ****************************************************************************** +.. * 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. +.. *******************************************************************************/ + +.. tabs:: + + .. group-tab:: oneAPI DPC++ + + Batch Processing: + + - :ref:`dpc_dbscan_brute_force_batch.cpp` + + .. group-tab:: oneAPI C++ + + Batch Processing: + + - :ref:`cpp_dbscan_brute_force_batch.cpp` + + .. group-tab:: Python* with DPC++ support + + Batch Processing: + + - :daal4py_sycl_example:`dbscan_batch.py` diff --git a/docs/source/includes/clustering/dbscan-introduction.rst b/docs/source/includes/clustering/dbscan-introduction.rst new file mode 100644 index 00000000000..d19e8129a0d --- /dev/null +++ b/docs/source/includes/clustering/dbscan-introduction.rst @@ -0,0 +1,31 @@ +.. ****************************************************************************** +.. * 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. +.. *******************************************************************************/ + +Density-based spatial clustering of applications with noise (DBSCAN) is a data clustering algorithm proposed in [Ester96]_. +It is a density-based clustering non-parametric algorithm: given a set of observations in some space, +it groups together observations that are closely packed together (observations with many nearby neighbors), +marking as outliers observations that lie alone in low-density regions (whose nearest neighbors are too far away). + +.. |c_math| replace:: :ref:`Compute ` +.. |c_input| replace:: :ref:`compute_input ` +.. |c_result| replace:: :ref:`compute_result ` +.. |c_op| replace:: :ref:`compute(...) ` + +=============== =========================== ======== =========== ============ + **Operation** **Computational methods** **Programming Interface** +--------------- --------------------------- --------------------------------- + |c_math| Default method |c_op| |c_input| |c_result| +=============== =========================== ======== =========== ============ diff --git a/docs/source/includes/clustering/dbscan-usage-examples.rst b/docs/source/includes/clustering/dbscan-usage-examples.rst new file mode 100644 index 00000000000..af6be8ecbe3 --- /dev/null +++ b/docs/source/includes/clustering/dbscan-usage-examples.rst @@ -0,0 +1,32 @@ +.. ****************************************************************************** +.. * 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. +.. *******************************************************************************/ + +Compute +------- + +:: + + void run_compute(const table& data, + const table& weights) { + double epsilon = 1.0; + std::int64_t max_observations = 5; + const auto dbscan_desc = kmeans::descriptor{epsilon, max_observations} + .set_result_options(dal::dbscan::result_options::responses); + + const auto result = compute(dbscan_desc, data, weights); + + print_table("responses", result.get_responses()); + } diff --git a/docs/source/includes/spmd/ccl-comm-usage-example.rst b/docs/source/includes/spmd/ccl-comm-usage-example.rst new file mode 100644 index 00000000000..dc5464e1387 --- /dev/null +++ b/docs/source/includes/spmd/ccl-comm-usage-example.rst @@ -0,0 +1,46 @@ +.. ****************************************************************************** +.. * 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. +.. *******************************************************************************/ + +.. highlight:: cpp +.. default-domain:: cpp + +:: + + #ifndef ONEDAL_DATA_PARALLEL + #define ONEDAL_DATA_PARALLEL + #endif + + #include "oneapi/dal/algo/kmeans.hpp" + #include "oneapi/dal/spmd/ccl/communicator.hpp" + + kmeans::model<> run_training(const table& data, + const table& initial_centroids) { + const auto kmeans_desc = kmeans::descriptor{} + .set_cluster_count(10) + .set_max_iteration_count(50) + .set_accuracy_threshold(1e-4); + + auto comm = dal::preview::spmd::make_communicator(queue); + auto rank_id = comm.get_rank(); + + const auto result_train = dal::preview::train(comm, kmeans_desc, local_input); + + if(rank_id == 0) { + print_table("centroids", result.get_model().get_centroids()); + print_value("objective", result.get_objective_function_value()); + } + return result.get_model(); + } \ No newline at end of file diff --git a/docs/source/includes/spmd/mpi-comm-usage-example.rst b/docs/source/includes/spmd/mpi-comm-usage-example.rst new file mode 100644 index 00000000000..ca1cc197dc6 --- /dev/null +++ b/docs/source/includes/spmd/mpi-comm-usage-example.rst @@ -0,0 +1,46 @@ +.. ****************************************************************************** +.. * 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. +.. *******************************************************************************/ + +.. highlight:: cpp +.. default-domain:: cpp + +:: + + #ifndef ONEDAL_DATA_PARALLEL + #define ONEDAL_DATA_PARALLEL + #endif + + #include "oneapi/dal/algo/kmeans.hpp" + #include "oneapi/dal/spmd/mpi/communicator.hpp" + + kmeans::model<> run_training(const table& data, + const table& initial_centroids) { + const auto kmeans_desc = kmeans::descriptor{} + .set_cluster_count(10) + .set_max_iteration_count(50) + .set_accuracy_threshold(1e-4); + + auto comm = dal::preview::spmd::make_communicator(queue); + auto rank_id = comm.get_rank(); + + const auto result_train = dal::preview::train(comm, kmeans_desc, local_input); + + if(rank_id == 0) { + print_table("centroids", result.get_model().get_centroids()); + print_value("objective", result.get_objective_function_value()); + } + return result.get_model(); + } \ No newline at end of file diff --git a/docs/source/oneapi-interfaces.rst b/docs/source/oneapi-interfaces.rst index 0fdafb54a69..573edeaaa1f 100644 --- a/docs/source/oneapi-interfaces.rst +++ b/docs/source/oneapi-interfaces.rst @@ -32,5 +32,6 @@ Refer to |daal-docs|_ official page for general information. onedal/programming-model/computational-modes.rst onedal/data-management/index.rst onedal/algorithms/index.rst + onedal/spmd/index.rst examples.rst onedal/appendix/index.rst diff --git a/docs/source/onedal/algorithms/clustering/dbscan.rst b/docs/source/onedal/algorithms/clustering/dbscan.rst new file mode 100644 index 00000000000..8e380f54b90 --- /dev/null +++ b/docs/source/onedal/algorithms/clustering/dbscan.rst @@ -0,0 +1,73 @@ +.. ****************************************************************************** +.. * 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. +.. *******************************************************************************/ + +.. highlight:: cpp +.. default-domain:: cpp + +.. re-use for math equations: +.. |x| replace:: :math:`x` +.. |y| replace:: :math:`y` + +.. _alg_dbscan: + +====== +DBSCAN +====== + +.. include:: ../../../includes/clustering/dbscan-introduction.rst + +------------------------ +Mathematical formulation +------------------------ + +.. _dbscan_c_math: + +Computation +----------- +Given the set :math:`X = \{x_1 = (x_{11}, \ldots, x_{1p}), \ldots, x_n = (x_{n1}, \ldots, x_{np})\}` +of :math:`n` :math:`p`-dimensional feature vectors (further referred as observations), +a positive floating-point number ``epsilon`` and a positive integer ``minObservations``, +the problem is to get clustering assignments for each input observation, based on the definitions below [Ester96]_: +two observations |x| and |y| are considered to be in the same cluster if there is a :term:`core observation` :math:`z`, +and |x| and |y| are both :term:`reachable` from :math:`z`. + +Each cluster gets a unique identifier, an integer number from :math:`0` to :math:`\text{total number of clusters } – 1`. +Each observation is assigned an identifier of the :term:`cluster` it belongs to, +or :math:`-1` if the observation considered to be a :term:`noise observation`. + +--------------------- +Programming Interface +--------------------- + +Refer to :ref:`API Reference: DBSCAN `. + +---------------- +Distributed mode +---------------- + +The algorithm supports distributed execution in SMPD mode (only on GPU). + +------------- +Usage example +------------- + +.. include:: ../../../includes/clustering/dbscan-usage-examples.rst + +-------- +Examples +-------- + +.. include:: ../../../includes/clustering/dbscan-examples.rst diff --git a/docs/source/onedal/algorithms/clustering/index.rst b/docs/source/onedal/algorithms/clustering/index.rst index 45ab5860dba..196f4e5b0bc 100644 --- a/docs/source/onedal/algorithms/clustering/index.rst +++ b/docs/source/onedal/algorithms/clustering/index.rst @@ -23,9 +23,14 @@ This chapter describes clustering algorithms implemented in |short_name|: .. toctree:: :titlesonly: + dbscan.rst kmeans.rst kmeans-init.rst +.. rubric:: Examples: DBSCAN + +.. include:: ../../../includes/clustering/dbscan-examples.rst + .. rubric:: Examples: K-Means .. include:: ../../../includes/clustering/kmeans-examples.rst diff --git a/docs/source/onedal/algorithms/ensembles/decision-forest.rst b/docs/source/onedal/algorithms/ensembles/decision-forest.rst index 3d0edaefa4f..1afaefcd801 100644 --- a/docs/source/onedal/algorithms/ensembles/decision-forest.rst +++ b/docs/source/onedal/algorithms/ensembles/decision-forest.rst @@ -343,3 +343,10 @@ Programming Interface --------------------- Refer to :ref:`API Reference: Decision Forest Classification and Regression `. + +---------------- +Distributed mode +---------------- + +The algorithm supports distributed execution in SMPD mode (only on GPU). + diff --git a/docs/source/onedal/algorithms/statistics/basic-statistics.rst b/docs/source/onedal/algorithms/statistics/basic-statistics.rst index bf671f51991..c8378e69c86 100755 --- a/docs/source/onedal/algorithms/statistics/basic-statistics.rst +++ b/docs/source/onedal/algorithms/statistics/basic-statistics.rst @@ -77,3 +77,9 @@ Programming Interface Refer to :ref:`API Reference: Basic statistics `. +---------------- +Distributed mode +---------------- + +The algorithm supports distributed execution in SMPD mode (only on GPU). + diff --git a/docs/source/onedal/glossary.rst b/docs/source/onedal/glossary.rst index c0a1884f95e..e1b700cde79 100644 --- a/docs/source/onedal/glossary.rst +++ b/docs/source/onedal/glossary.rst @@ -437,3 +437,23 @@ Common oneAPI terms SYCL(TM) [SYCLSpec]_ --- high-level programming model for OpenCL(TM) that enables code for heterogeneous processors to be written in a "single-source" style using completely standard C++. + +Distributed computational mode terms +==================================== + +.. glossary:: + :sorted: + + SPMD + Single Program, Multiple Data (SPMD) is a technique employed to achieve parallelism. + In SPMD model, multiple autonomous processors simultaneously execute the same program at independent points. + + Communicator + A |short_name| concept for an object that is used to perform inter-process collective + operations + + Communicator backend + A particular library providing collective operations. + + **Examples:** oneCCL, oneMPI + diff --git a/docs/source/onedal/spmd/_static/spmd_flow.png b/docs/source/onedal/spmd/_static/spmd_flow.png new file mode 100755 index 0000000000000000000000000000000000000000..65497b9a67bb25a2031d27119618829adda5849e GIT binary patch literal 23601 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