/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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. */ #ifndef TVM_RUNTIME_DISCO_BUILTIN_H_ #define TVM_RUNTIME_DISCO_BUILTIN_H_ #include #include #include #include namespace tvm { namespace runtime { /*! * \brief Possible kinds of reduction operations. */ enum class ReduceKind : int32_t { kSum = 0, kProd = 1, kMin = 2, kMax = 3, kAvg = 4, }; /*! \brief Converts `ReduceKind` to string */ inline std::string ReduceKind2String(ReduceKind kind) { switch (kind) { case ReduceKind::kSum: return "kSum"; case ReduceKind::kProd: return "kProd"; case ReduceKind::kMin: return "kMin"; case ReduceKind::kMax: return "kMax"; case ReduceKind::kAvg: return "kAvg"; } TVM_FFI_THROW(ValueError) << "Unknown ReduceKind: " << static_cast(kind); } /*! * \brief Load a runtime Module, then create and initialize a RelaxVM * \param path The path to the runtime Module (a DSO file) to be loaded * \param device The default device used to initialize the RelaxVM * \return The RelaxVM as a runtime Module */ TVM_RUNTIME_DLL ffi::Module LoadVMModule(std::string path, ffi::Optional device); /*! * \brief Create an uninitialized empty Tensor * \param shape The shape of the Tensor * \param dtype The dtype of the Tensor * \param device The device the Tensor is created on. If None, use the thread local default device * \return The Tensor created */ TVM_RUNTIME_DLL Tensor DiscoEmptyTensor(ffi::Shape shape, DLDataType dtype, ffi::Optional device); /*! * \brief Perform an allreduce operation using the underlying communication library * \param send The array send to perform allreduce on * \param reduce_kind The kind of reduction operation (e.g. sum, avg, min, max) * \param in_group Whether the allreduce operation performs globally or in group as default. * \param recv The array receives the outcome of allreduce */ TVM_RUNTIME_DLL void AllReduce(Tensor send, ReduceKind reduce_kind, bool in_group, Tensor recv); /*! * \brief Perform an allgather operation using the underlying communication library * \param send The array send to perform allgather on * \param in_group Whether the allgather operation performs globally or in group as default. * \param recv The array receives the outcome of allgather */ TVM_RUNTIME_DLL void AllGather(Tensor send, bool in_group, Tensor recv); /*! * \brief Perform a broadcast operation from worker-0 * \param send The buffer to be broadcasted * \param in_group Whether the broadcast operation performs globally or in group as default. * \param recv The buffer receives the broadcasted array */ TVM_RUNTIME_DLL void BroadcastFromWorker0(Tensor send, bool in_group, Tensor recv); /*! * \brief Perform a scatter operation from worker-0, chunking the given buffer into equal parts. * \param send For worker-0, it must be provided, and otherwise, the buffer must be None. * The buffer will be divided into equal parts and sent to each worker accordingly. * \param in_group Whether the scatter operation performs globally or in group as default. * \param recv The receiving buffer, which must not be None. */ TVM_RUNTIME_DLL void ScatterFromWorker0(ffi::Optional send, bool in_group, Tensor recv); /*! * \brief Perform a gather operation to worker-0. * \param send The sending buffer, which must not be None. * \param in_group Whether the gather operation performs globally or in group as default. * \param recv For worker-0, it must be provided, and otherwise, the buffer must be None. The * receiving buffer will be divided into equal parts and receive from each worker accordingly. */ TVM_RUNTIME_DLL void GatherToWorker0(Tensor send, bool in_group, ffi::Optional recv); /*! * \brief Receive a buffer from worker-0. No-op if the current worker is worker-0. * \param buffer The buffer to be received */ TVM_RUNTIME_DLL void RecvFromWorker0(Tensor buffer); /*! * \brief Send a buffer to the corresponding worker in the next group. * An error is thrown if the worker is already in the last group. * \param buffer The sending buffer. */ TVM_RUNTIME_DLL void SendToNextGroup(Tensor buffer); /*! * \brief Receive a buffer from the corresponding worker in the previous group. * An error is thrown if the worker is already in the first group. * \param buffer The receiving buffer. */ TVM_RUNTIME_DLL void RecvFromPrevGroup(Tensor buffer); /*! * \brief Send a buffer to the target receiver worker (globally across all groups). * \param buffer The sending buffer. * \param receiver_id The global receiver worker id. */ TVM_RUNTIME_DLL void SendToWorker(Tensor buffer, int receiver_id); /*! * \brief Receive a buffer from the target sender worker (globally across all groups). * \param buffer The receiving buffer. * \param sender_id The global sender worker id. */ TVM_RUNTIME_DLL void RecvFromWorker(Tensor buffer, int sender_id); /*! \brief Get the local worker id */ TVM_RUNTIME_DLL int WorkerId(); /*! * \brief Called by the worker thread. Waiting until the worker completes all its tasks. * As a specific example, on a CUDA worker, it blocks until all kernels are launched and * cudaStreamSynchronize is complete. */ TVM_RUNTIME_DLL void SyncWorker(); } // namespace runtime } // namespace tvm #endif // TVM_RUNTIME_DISCO_BUILTIN_H_