Skip to content

include/tenzr/sharding/mesh.h

Namespaces

Name
tenzr

Classes

Name
class tenzr::Mesh
Named grid of devices defining axes used by sharding specifications.

Source code

// Copyright 2026 The Tenzr Project Authors
//
// SPDX-License-Identifier: Apache-2.0
//
// 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
//
//      https://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.

#ifndef TENZR_SHARDING_MESH_H_
#define TENZR_SHARDING_MESH_H_

#include <algorithm>
#include <cstdint>
#include <numeric>
#include <sstream>
#include <stdexcept>
#include <string>
#include <string_view>
#include <vector>

#include "tenzr/common/error.h"
#include "tenzr/common/export.h"

namespace tenzr {

  class TENZR_API Mesh {
   public:
    Mesh() : devices_{0}, shape_{1}, axis_names_{"x"} {}

    Mesh(std::vector<int64_t> devices, std::vector<int64_t> shape, std::vector<std::string> axis_names)
        : devices_(std::move(devices)), shape_(std::move(shape)), axis_names_(std::move(axis_names)) {
      Validate();
    }

    Mesh(std::vector<int64_t> shape, std::vector<std::string> axis_names) : shape_(std::move(shape)), axis_names_(std::move(axis_names)) {
      int64_t total = 1;
      for (int64_t dim : shape_) {
        total *= dim;
      }
      devices_.resize(static_cast<size_t>(total));
      std::iota(devices_.begin(), devices_.end(), 0);
      Validate();
    }

    [[nodiscard]] size_t Ndim() const noexcept { return shape_.size(); }

    [[nodiscard]] int64_t NumDevices() const noexcept { return static_cast<int64_t>(devices_.size()); }

    [[nodiscard]] int64_t Size() const noexcept { return NumDevices(); }

    [[nodiscard]] bool Empty() const noexcept { return devices_.empty(); }

    [[nodiscard]] const std::vector<int64_t>& shape() const noexcept { return shape_; }

    [[nodiscard]] const std::vector<std::string>& AxisNames() const noexcept { return axis_names_; }

    [[nodiscard]] const std::vector<int64_t>& Devices() const noexcept { return devices_; }

    [[nodiscard]] int64_t AxisSize(std::string_view axis_name) const {
      for (size_t i = 0; i < axis_names_.size(); ++i) {
        if (axis_names_[i] == axis_name) {
          return shape_[i];
        }
      }
      TENZR_THROW("Mesh axis not found: " + std::string(axis_name));
    }

    [[nodiscard]] int64_t AxisIndex(std::string_view axis_name) const {
      for (size_t i = 0; i < axis_names_.size(); ++i) {
        if (axis_names_[i] == axis_name) {
          return static_cast<int64_t>(i);
        }
      }
      return -1;
    }

    [[nodiscard]] bool HasAxis(std::string_view axis_name) const noexcept { return AxisIndex(axis_name) >= 0; }

    [[nodiscard]] std::vector<int64_t> DeviceCoords(int64_t device_id) const {
      auto it = std::find(devices_.begin(), devices_.end(), device_id);
      if (it == devices_.end()) {
        TENZR_THROW("Device ID " + std::to_string(device_id) + " not in Mesh");
      }
      size_t flat_idx = static_cast<size_t>(std::distance(devices_.begin(), it));
      std::vector<int64_t> coords(shape_.size());
      for (int64_t d = static_cast<int64_t>(shape_.size()) - 1; d >= 0; --d) {
        coords[static_cast<size_t>(d)] = static_cast<int64_t>(flat_idx % static_cast<size_t>(shape_[static_cast<size_t>(d)]));
        flat_idx /= static_cast<size_t>(shape_[static_cast<size_t>(d)]);
      }
      return coords;
    }

    [[nodiscard]] int64_t DeviceAt(const std::vector<int64_t>& coords) const {
      if (coords.size() != shape_.size()) {
        TENZR_THROW("Coordinates rank mismatch with Mesh rank");
      }
      size_t flat_idx = 0;
      for (size_t i = 0; i < coords.size(); ++i) {
        if (coords[i] < 0 || coords[i] >= shape_[i]) {
          TENZR_THROW("Coordinate out of range for axis " + axis_names_[i]);
        }
        flat_idx = flat_idx * static_cast<size_t>(shape_[i]) + static_cast<size_t>(coords[i]);
      }
      return devices_[flat_idx];
    }

    [[nodiscard]] std::string ToString() const {
      std::ostringstream oss;
      oss << "Mesh(shape={";
      for (size_t i = 0; i < shape_.size(); ++i) {
        if (i > 0) {
          oss << ", ";
        }
        oss << "'" << axis_names_[i] << "': " << shape_[i];
      }
      oss << "}, num_devices=" << devices_.size() << ")";
      return oss.str();
    }

    [[nodiscard]] std::string ToShardyMeshDecl(std::string_view mesh_sym = "mesh") const {
      std::ostringstream oss;
      oss << "sdy.mesh @" << mesh_sym << " = <[";
      for (size_t i = 0; i < shape_.size(); ++i) {
        if (i > 0) {
          oss << ", ";
        }
        oss << "\"" << axis_names_[i] << "\"=" << shape_[i];
      }
      oss << "]>";
      return oss.str();
    }

    bool operator==(const Mesh& other) const noexcept { return shape_ == other.shape_ && axis_names_ == other.axis_names_ && devices_ == other.devices_; }

    bool operator!=(const Mesh& other) const noexcept { return !(*this == other); }

   private:
    void Validate() {
      if (shape_.size() != axis_names_.size()) {
        TENZR_THROW("Mesh shape rank must match axis_names count");
      }
      int64_t expected_total = 1;
      for (int64_t dim : shape_) {
        if (dim <= 0) {
          TENZR_THROW("Mesh dimensions must be strictly positive");
        }
        expected_total *= dim;
      }
      if (static_cast<int64_t>(devices_.size()) != expected_total) {
        TENZR_THROW("Mesh devices count (" + std::to_string(devices_.size()) + ") does not match grid product (" + std::to_string(expected_total) + ")");
      }
    }

    std::vector<int64_t> devices_;
    std::vector<int64_t> shape_;
    std::vector<std::string> axis_names_;
  };

}  // namespace tenzr

#endif  // TENZR_SHARDING_MESH_H_