Skip to content

Commit ce58b93

Browse files
authored
Added distributed tensor type (#1210)
* Add experimental distributed tensor support
1 parent 9184aa3 commit ce58b93

20 files changed

Lines changed: 2938 additions & 258 deletions

CMakeLists.txt

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,6 @@ option(MATX_BUILD_BENCHMARKS "Build benchmarks" OFF)
7070
option(MATX_NVTX_FLAGS "Enable NVTX Macros" OFF)
7171
option(MATX_BUILD_DOCS "Build documentation" OFF)
7272
option(MATX_BUILD_32_BIT "Build with 32-bit indexing support" OFF)
73-
option(MATX_MULTI_GPU "Multi-GPU support" OFF)
7473
option(MATX_EN_VISUALIZATION "Enable visualization support" OFF)
7574
#option(MATX_EN_CUTLASS OFF)
7675
option(MATX_EN_CUTENSOR OFF)
@@ -417,11 +416,6 @@ if (MATX_EN_CUDSS)
417416
target_link_libraries(matx INTERFACE cuDSS::cuDSS)
418417
endif()
419418

420-
if (MATX_MULTI_GPU)
421-
include(cmake/FindNvshmem.cmake)
422-
find_package(Nvshmem REQUIRED)
423-
endif()
424-
425419
# Find python3 and pybind11 for generating unit tests and benchmarks
426420
if (MATX_EN_FILEIO OR MATX_EN_VISUALIZATION OR MATX_EN_PYBIND11 OR MATX_BUILD_EXAMPLES OR MATX_BUILD_TESTS OR MATX_BUILD_BENCHMARKS)
427421
message(STATUS "Enabling pybind11 support")

cmake/FindNvshmem.cmake

Lines changed: 0 additions & 48 deletions
This file was deleted.

docker/production/matx-production.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#!/usr/bin/env python
22

33
import hpccm
4-
from hpccm.building_blocks import gnu, mlnx_ofed, nvshmem, cmake
4+
from hpccm.building_blocks import gnu, mlnx_ofed, cmake
55
from hpccm.primitives import baseimage
66

77
DOXYGEN_VER = "1.9.6"

docs_input/build.rst

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -198,8 +198,6 @@ Unless otherwise noted, these options are OFF by default.
198198
- ``-DMATX_EN_BLIS=ON``
199199
* - OpenBLAS Support
200200
- ``-DMATX_EN_OPENBLAS=ON``
201-
* - Multi-GPU Support
202-
- ``-DMATX_MULTI_GPU=ON``
203201
* - Disable CUB Caching
204202
- ``-DMATX_DISABLE_CUB_CACHE=ON``
205203
* - Enable NVIDIA MathDx support for kernel fusion
Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
.. _distributed-tensors:
2+
3+
Experimental Distributed Tensors
4+
################################
5+
6+
Status and goals
7+
================
8+
9+
``experimental::distributed_tensor_t`` is a prototype for representing one
10+
logical tensor whose storage is split across CUDA devices and, eventually,
11+
processes. The prototype currently executes single-process, multi-GPU
12+
pointwise work, batch-local ``matmul``, ``chol``, and ``fft``, and gathers a
13+
distributed tensor into a regular tensor. It is not yet a general distributed
14+
MatX operator system.
15+
16+
The logical tensor has exactly one element type and rank. Every local fragment
17+
is a ``tensor_t<T, RANK>``. Fragment extents, strides, process ranks, device
18+
IDs, and allocation sizes may differ, but fragment value types may not.
19+
20+
Wrapping existing storage
21+
=========================
22+
23+
``make_distributed_tensor`` can allocate each local fragment, or it can wrap
24+
existing device pointers. The short forms accept one pointer when the process
25+
owns exactly one fragment, or a vector ordered by increasing distribution
26+
fragment index:
27+
28+
.. code-block:: cpp
29+
30+
auto local = make_tensor<float>({local_count}, MATX_DEVICE_MEMORY);
31+
auto distributed =
32+
make_distributed_tensor(layout, context, local.Data());
33+
34+
std::vector<float *> pointers{gpu0_pointer, gpu1_pointer};
35+
auto distributed_many =
36+
make_distributed_tensor(layout, context, pointers);
37+
38+
For nontrivial mappings, use ``distributed_local_pointer_t`` to bind pointers
39+
to explicit distribution indices. Its optional ``owner`` is a
40+
``std::shared_ptr<void>`` lifetime token for backend-owned allocations:
41+
42+
.. code-block:: cpp
43+
44+
std::vector<distributed_local_pointer_t<float>> bindings{
45+
{3, gpu1_pointer, backend_owner},
46+
{1, gpu0_pointer, backend_owner}};
47+
auto distributed =
48+
make_distributed_tensor(layout, context, bindings);
49+
50+
Pointers are otherwise non-owning. The caller must keep their allocations alive
51+
and must supply storage large enough for the corresponding local shape. Only
52+
fragments owned by the current process and one of its local devices may be
53+
bound.
54+
55+
Pointwise execution
56+
===================
57+
58+
``apply`` accepts either ordinary inputs or distributed inputs. Distributed and
59+
ordinary tensor inputs cannot be mixed in one call. Distributed inputs may have
60+
different element types, but they and the output must have the same global
61+
shape, context, and exact fragment layout; the callable's result type must
62+
exactly match the output type. The executor builds an ordinary ``matx::apply``
63+
expression for each group of corresponding local views and launches it on that
64+
fragment's device and stream. It performs no peer copies, collectives, or
65+
implicit redistribution.
66+
67+
For example:
68+
69+
.. code-block:: cpp
70+
71+
using namespace matx::experimental;
72+
73+
distributed_context context{{0, 1}};
74+
distributedCUDAExecutor exec{context};
75+
auto layout = block_distribution_t<1>::Slab({count}, {{0, 0}, {0, 1}});
76+
77+
auto a = make_distributed_tensor<float>(layout, context);
78+
auto b = make_distributed_tensor<float>(layout, context);
79+
auto output = make_distributed_tensor<float>(layout, context);
80+
81+
auto add = [] __host__ __device__ (float x, float y) { return x + y; };
82+
(output = apply(add, a, b)).run(exec);
83+
exec.sync();
84+
85+
Input fragments are initialized through ``LocalView(i)``. Assignment from a
86+
regular tensor to a distributed tensor is intentionally unavailable because it
87+
would hide a scatter and its distribution policy.
88+
89+
Batch-local transforms
90+
======================
91+
92+
The first transform paths reuse the ordinary ``matmul``, ``chol``, and ``fft``
93+
names. When operands are distributed tensors, the executor constructs the
94+
existing local MatX operation for each aligned fragment and runs it on that
95+
fragment's device stream:
96+
97+
.. code-block:: cpp
98+
99+
auto layout = block_distribution_t<3>::Slab(
100+
{batch_count, rows, columns}, {{0, 0}, {0, 1}}, 0);
101+
auto a = make_distributed_tensor<float>(layout, context);
102+
auto b = make_distributed_tensor<float>(layout, context);
103+
auto c = make_distributed_tensor<float>(layout, context);
104+
105+
(c = matmul(a, b)).run(exec);
106+
exec.sync();
107+
108+
This is data parallelism, not a distributed transform within a matrix or FFT.
109+
Leading batch dimensions may be partitioned, but the trailing two matrix
110+
dimensions for ``matmul`` and ``chol``, or trailing FFT dimension for ``fft``,
111+
must be fully local. Inputs and output must have aligned batch fragments and
112+
endpoints. The operation performs no communication, and each local call uses
113+
the same regular MatX accelerated path it would use for a non-distributed
114+
tensor.
115+
116+
Materialization
117+
===============
118+
119+
A distributed tensor can be assigned to a same-type, same-rank regular tensor:
120+
121+
.. code-block:: cpp
122+
123+
auto gathered = make_tensor<float>({count});
124+
(gathered = output).run(exec);
125+
exec.sync();
126+
127+
The current implementation copies fragments directly into canonical global
128+
row-major order and supports contiguous or strided regular destinations. It
129+
uses unified memory or direct CUDA peer access when source and destination are
130+
on different devices. Host staging is not used; materialization into device
131+
memory fails when direct access is unavailable.
132+
133+
The specified multi-process meaning of this assignment is a collective
134+
all-gather: every participating process receives a complete regular tensor.
135+
The current executor rejects contexts with more than one process until a
136+
collective backend is attached. A future root-only gather will use an explicit
137+
API rather than changing assignment semantics.
138+
139+
Limitations and next steps
140+
==========================
141+
142+
* Only one process is executable today; no optional communication dependency is
143+
introduced by the core type.
144+
* Pointwise operations require identical layouts. Batch-local transforms
145+
require aligned batch fragments and fully local operation dimensions.
146+
Redistribution and scattering will be explicit operations.
147+
* Other distributed BLAS, solver, reduction, DLPack, printing, and global
148+
element-access paths are not provided yet.
149+
* Materialization enqueues copies on the per-endpoint CUDA streams;
150+
``distributedCUDAExecutor::sync`` is the completion boundary.

docs_input/developer_guide/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,5 @@ terminology used in the MatX code base.
1212

1313
operators.rst
1414
transforms.rst
15+
distributed_tensors.rst
1516
docs.rst

0 commit comments

Comments
 (0)