Files
2026-07-13 12:40:42 +08:00

209 lines
7.8 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// Copyright (c) 2026 CINN Authors. All Rights Reserved.
//
// 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 <array>
#include <memory>
#include <optional>
#include <string>
#include <vector>
#include "paddle/cinn/runtime/backend_api.h"
#include "paddle/phi/backends/device_ext.h"
#include "paddle/phi/common/place.h"
#ifdef CINN_WITH_CUSTOM_DEVICE
namespace cinn {
namespace runtime {
class CustomModule {
public:
virtual ~CustomModule() = default;
virtual void* GetFunction(const std::string& func_name) = 0;
};
namespace custom_device {
// ============================================================
// Part 1: CINN Compilation and Runtime Strategy Abstract Interfaces
// ============================================================
// Compiler Toolchain Interface: Responsible for invoking external compilers
class CustomCompilerToolchain {
public:
virtual ~CustomCompilerToolchain() = default;
virtual std::string Compile(const std::string& code) = 0;
virtual std::string GetRuntimeSource() = 0;
};
// Runtime Strategy Interface: Responsible for loading and launching Kernels
class CustomRuntimeStrategy {
public:
virtual ~CustomRuntimeStrategy() = default;
virtual std::unique_ptr<cinn::runtime::CustomModule> LoadModule(
const std::string& path) = 0;
virtual void LaunchKernel(void* func_ptr,
const std::string& func_name,
void** args,
int num_args,
int grid_x,
int grid_y,
int grid_z,
int block_x,
int block_y,
int block_z,
int shared_mem,
void* stream) = 0;
};
// Compilation Optimization Interface: Responsible for vendor-specific
// Fusion/Schedule/Pass
class CustomCompileStrategy {
public:
virtual ~CustomCompileStrategy() = default;
virtual bool ApplyCustomPass(void* ir_module) { return false; }
};
// ============================================================
// Part 2: Plugin Management Class
// ============================================================
/// @brief Top-level CINN plugin management class for a custom hardware device.
///
/// CinnCustomDevicePlugin acts as the single entry point through which CINN's
/// compiler and runtime subsystems access vendor-provided capabilities. Each
/// custom device type (identified by its phi::Place) owns exactly one
/// singleton instance.
///
/// A vendor plugin initialises the instance by calling InitWrappers() with a
/// C_CinnInterface pointer obtained from C_DeviceInterface::cinn_interface.
/// After initialisation, callers can retrieve the three strategy objects:
///
/// - CustomCompilerToolchain invokes the vendor compiler to translate
/// device-specific IR/source into an executable module.
/// - CustomRuntimeStrategy loads a compiled module and dispatches
/// kernel launches to the device.
/// - CustomCompileStrategy applies vendor-specific fusion/schedule/pass
/// optimisations at the CINN IR level.
///
/// Usage example:
/// @code
/// auto& plugin = CinnCustomDevicePlugin::GetInstance(place);
/// plugin.GetToolchain()->Compile(source_code);
/// plugin.GetRuntime()->LaunchKernel(...);
/// @endcode
///
/// @note This class is non-copyable. All three strategy objects are lazily
/// constructed during InitWrappers(); if the vendor does not implement
/// a given C hook the corresponding strategy pointer may be null.
class PADDLE_API CinnCustomDevicePlugin {
public:
CinnCustomDevicePlugin() = default;
~CinnCustomDevicePlugin() = default;
/// @brief Returns the per-place singleton CinnCustomDevicePlugin instance.
///
/// @param[in] place The phi::Place identifying the custom device type and
/// device index for which the plugin is requested.
/// @return Reference to the singleton plugin for the given place.
static CinnCustomDevicePlugin& GetInstance(const phi::Place& place);
/// @brief Returns the compiler toolchain strategy for this device.
///
/// The toolchain is responsible for invoking the vendor compiler and
/// providing runtime source headers required by generated kernels.
/// Returns nullptr if the vendor plugin does not implement the compile hook.
CustomCompilerToolchain* GetToolchain() { return toolchain_.get(); }
/// @brief Returns the runtime strategy for this device.
///
/// The runtime strategy handles module loading and kernel launch dispatch.
/// Returns nullptr if the vendor plugin does not implement runtime hooks.
CustomRuntimeStrategy* GetRuntime() { return runtime_strategy_.get(); }
/// @brief Returns the compile-time optimisation strategy for this device.
///
/// The compile strategy allows vendors to inject custom IR passes (e.g.,
/// hardware-specific fusion rules) into the CINN compilation pipeline.
/// Returns nullptr if the vendor plugin does not implement the pass hook.
CustomCompileStrategy* GetCompileStrategy() {
return compile_strategy_.get();
}
/// @brief Initialises the three strategy wrappers from a C_CinnInterface.
///
/// Called once during plugin registration (triggered by
/// C_DeviceInterface::cinn_interface). Constructs internal wrapper objects
/// that delegate to the function pointers provided by @p cif.
///
/// @param[in] cif Pointer to the vendor-supplied C_CinnInterface struct.
/// Must remain valid for the lifetime of this plugin
/// instance. Passing nullptr is a no-op.
void InitWrappers(C_CinnInterface* cif);
private:
std::unique_ptr<CustomCompilerToolchain> toolchain_;
std::unique_ptr<CustomRuntimeStrategy> runtime_strategy_;
std::unique_ptr<CustomCompileStrategy> compile_strategy_;
// Disable copying
CinnCustomDevicePlugin(const CinnCustomDevicePlugin&) = delete;
CinnCustomDevicePlugin& operator=(const CinnCustomDevicePlugin&) = delete;
};
// ============================================================
// Part 3: BackendAPI Implementation (Core Runtime Interface)
// ============================================================
class CustomBackendAPI final : public BackendAPI {
public:
CustomBackendAPI() = default;
~CustomBackendAPI() = default;
// Global access point
static CustomBackendAPI* Global();
// Device Management
void set_device(int device_id) override;
int get_device() override;
// Memory Management
void* malloc(size_t numBytes) override;
void free(void* data) override;
void memset(void* data, int value, size_t numBytes) override;
void memcpy(void* dest,
const void* src,
size_t numBytes,
MemcpyType type) override;
// Synchronization
void device_sync() override;
void stream_sync(void* stream) override;
// Property Query
int get_device_property(DeviceProperty device_property,
std::optional<int> device_id = std::nullopt) override;
std::array<int, 3> get_max_grid_dims(
std::optional<int> device_id = std::nullopt) override;
std::array<int, 3> get_max_block_dims(
std::optional<int> device_id = std::nullopt) override;
};
} // namespace custom_device
} // namespace runtime
} // namespace cinn
#endif // CINN_WITH_CUSTOM_DEVICE