1*523fa7a6SAndroid Build Coastguard Worker /* 2*523fa7a6SAndroid Build Coastguard Worker * Copyright (c) Meta Platforms, Inc. and affiliates. 3*523fa7a6SAndroid Build Coastguard Worker * All rights reserved. 4*523fa7a6SAndroid Build Coastguard Worker * 5*523fa7a6SAndroid Build Coastguard Worker * This source code is licensed under the BSD-style license found in the 6*523fa7a6SAndroid Build Coastguard Worker * LICENSE file in the root directory of this source tree. 7*523fa7a6SAndroid Build Coastguard Worker */ 8*523fa7a6SAndroid Build Coastguard Worker 9*523fa7a6SAndroid Build Coastguard Worker #pragma once 10*523fa7a6SAndroid Build Coastguard Worker 11*523fa7a6SAndroid Build Coastguard Worker #include <cstring> 12*523fa7a6SAndroid Build Coastguard Worker 13*523fa7a6SAndroid Build Coastguard Worker #include <executorch/runtime/backend/backend_execution_context.h> 14*523fa7a6SAndroid Build Coastguard Worker #include <executorch/runtime/backend/backend_init_context.h> 15*523fa7a6SAndroid Build Coastguard Worker #include <executorch/runtime/core/array_ref.h> 16*523fa7a6SAndroid Build Coastguard Worker #include <executorch/runtime/core/error.h> 17*523fa7a6SAndroid Build Coastguard Worker #include <executorch/runtime/core/evalue.h> 18*523fa7a6SAndroid Build Coastguard Worker #include <executorch/runtime/core/freeable_buffer.h> 19*523fa7a6SAndroid Build Coastguard Worker #include <executorch/runtime/core/memory_allocator.h> 20*523fa7a6SAndroid Build Coastguard Worker #include <executorch/runtime/core/result.h> 21*523fa7a6SAndroid Build Coastguard Worker #include <executorch/runtime/platform/compiler.h> 22*523fa7a6SAndroid Build Coastguard Worker 23*523fa7a6SAndroid Build Coastguard Worker namespace executorch { 24*523fa7a6SAndroid Build Coastguard Worker namespace runtime { 25*523fa7a6SAndroid Build Coastguard Worker 26*523fa7a6SAndroid Build Coastguard Worker struct SizedBuffer { 27*523fa7a6SAndroid Build Coastguard Worker void* buffer; 28*523fa7a6SAndroid Build Coastguard Worker size_t nbytes; // number of bytes of buffer 29*523fa7a6SAndroid Build Coastguard Worker }; 30*523fa7a6SAndroid Build Coastguard Worker 31*523fa7a6SAndroid Build Coastguard Worker struct CompileSpec { 32*523fa7a6SAndroid Build Coastguard Worker const char* key; // spec key 33*523fa7a6SAndroid Build Coastguard Worker SizedBuffer value; // spec value 34*523fa7a6SAndroid Build Coastguard Worker }; 35*523fa7a6SAndroid Build Coastguard Worker 36*523fa7a6SAndroid Build Coastguard Worker /** 37*523fa7a6SAndroid Build Coastguard Worker * An opaque handle managed by a backend. Typically points to a backend-private 38*523fa7a6SAndroid Build Coastguard Worker * class/struct. 39*523fa7a6SAndroid Build Coastguard Worker */ 40*523fa7a6SAndroid Build Coastguard Worker using DelegateHandle = void; 41*523fa7a6SAndroid Build Coastguard Worker 42*523fa7a6SAndroid Build Coastguard Worker class BackendInterface { 43*523fa7a6SAndroid Build Coastguard Worker public: 44*523fa7a6SAndroid Build Coastguard Worker virtual ~BackendInterface() = 0; 45*523fa7a6SAndroid Build Coastguard Worker 46*523fa7a6SAndroid Build Coastguard Worker /** 47*523fa7a6SAndroid Build Coastguard Worker * Returns true if the backend is available to process delegation calls. 48*523fa7a6SAndroid Build Coastguard Worker */ 49*523fa7a6SAndroid Build Coastguard Worker ET_NODISCARD virtual bool is_available() const = 0; 50*523fa7a6SAndroid Build Coastguard Worker 51*523fa7a6SAndroid Build Coastguard Worker /** 52*523fa7a6SAndroid Build Coastguard Worker * Responsible to further process (compile/transform/optimize) the compiled 53*523fa7a6SAndroid Build Coastguard Worker * unit that was produced, ahead-of-time, as well as perform any backend 54*523fa7a6SAndroid Build Coastguard Worker * initialization to ready it for execution. This method is called every time 55*523fa7a6SAndroid Build Coastguard Worker * the ExecuTorch program is initialized. Consequently, this is the place to 56*523fa7a6SAndroid Build Coastguard Worker * perform any backend initialization as well as transformations, 57*523fa7a6SAndroid Build Coastguard Worker * optimizations, and even compilation that depend on the target device. As 58*523fa7a6SAndroid Build Coastguard Worker * such, it is strongly encouraged to push as much processing as possible to 59*523fa7a6SAndroid Build Coastguard Worker * the ahead-of-time processing. 60*523fa7a6SAndroid Build Coastguard Worker * 61*523fa7a6SAndroid Build Coastguard Worker * @param[in] processed An opaque (to ExecuTorch) backend-specific compiled 62*523fa7a6SAndroid Build Coastguard Worker * unit from the preprocessor. Can contain anything the backend needs to 63*523fa7a6SAndroid Build Coastguard Worker * execute the equivalent semantics of the passed-in Module and its 64*523fa7a6SAndroid Build Coastguard Worker * method. Often passed unmodified to `execute()` as a `DelegateHandle`, 65*523fa7a6SAndroid Build Coastguard Worker * unless it needs further processing at init time to be fully executable. 66*523fa7a6SAndroid Build Coastguard Worker * If the data is not needed after init(), calling processed->Free() can 67*523fa7a6SAndroid Build Coastguard Worker * reclaim its memory. 68*523fa7a6SAndroid Build Coastguard Worker * @param[in] compile_specs The exact same compiler specification that 69*523fa7a6SAndroid Build Coastguard Worker * was used ahead-of-time to produce `processed`. 70*523fa7a6SAndroid Build Coastguard Worker * 71*523fa7a6SAndroid Build Coastguard Worker * @returns On success, an opaque handle representing the the method 72*523fa7a6SAndroid Build Coastguard Worker * implemented by the delegate. This handle is passed to `execute()` and 73*523fa7a6SAndroid Build Coastguard Worker * `destroy()`, and the memory it points to is owned by the backend. 74*523fa7a6SAndroid Build Coastguard Worker * Typically points to a backend-private class/struct. 75*523fa7a6SAndroid Build Coastguard Worker * @returns On error, returns an error code other than Error::Ok. If the 76*523fa7a6SAndroid Build Coastguard Worker * compiled unit (the preprocessed result from ahead of time) is not 77*523fa7a6SAndroid Build Coastguard Worker * compatible with the current backend runtime, return the error code 78*523fa7a6SAndroid Build Coastguard Worker * Error::DelegateInvalidCompatibility. Other backend delegate 79*523fa7a6SAndroid Build Coastguard Worker * specific error codes can be found in error.h. 80*523fa7a6SAndroid Build Coastguard Worker */ 81*523fa7a6SAndroid Build Coastguard Worker ET_NODISCARD virtual Result<DelegateHandle*> init( 82*523fa7a6SAndroid Build Coastguard Worker BackendInitContext& context, 83*523fa7a6SAndroid Build Coastguard Worker FreeableBuffer* processed, 84*523fa7a6SAndroid Build Coastguard Worker ArrayRef<CompileSpec> compile_specs) const = 0; 85*523fa7a6SAndroid Build Coastguard Worker 86*523fa7a6SAndroid Build Coastguard Worker /** 87*523fa7a6SAndroid Build Coastguard Worker * Responsible for executing the given method’s handle, as it was produced 88*523fa7a6SAndroid Build Coastguard Worker * by compile. 89*523fa7a6SAndroid Build Coastguard Worker * 90*523fa7a6SAndroid Build Coastguard Worker * @param[in] handle An opaque handle returned by `init()`. Usually a backend 91*523fa7a6SAndroid Build Coastguard Worker * executable unit. This executable unit should be ready to execute the 92*523fa7a6SAndroid Build Coastguard Worker * delegate blobs. 93*523fa7a6SAndroid Build Coastguard Worker * @param[in] args The method’s inputs and outputs. 94*523fa7a6SAndroid Build Coastguard Worker * @retval Error::Ok if successful. 95*523fa7a6SAndroid Build Coastguard Worker */ 96*523fa7a6SAndroid Build Coastguard Worker ET_NODISCARD virtual Error execute( 97*523fa7a6SAndroid Build Coastguard Worker BackendExecutionContext& context, 98*523fa7a6SAndroid Build Coastguard Worker DelegateHandle* handle, 99*523fa7a6SAndroid Build Coastguard Worker EValue** args) const = 0; 100*523fa7a6SAndroid Build Coastguard Worker 101*523fa7a6SAndroid Build Coastguard Worker /** 102*523fa7a6SAndroid Build Coastguard Worker * Responsible for destroying a handle, if it's required for some backend. 103*523fa7a6SAndroid Build Coastguard Worker * It may be needed for some backends. For example, resources associated with 104*523fa7a6SAndroid Build Coastguard Worker * this handle needs to be released. This method is called when the execution 105*523fa7a6SAndroid Build Coastguard Worker * plan is destroyed (i.e., the program is out of its lifespan). 106*523fa7a6SAndroid Build Coastguard Worker * 107*523fa7a6SAndroid Build Coastguard Worker * @param[in] handle The handle to be destroyed. An opaque handle returned by 108*523fa7a6SAndroid Build Coastguard Worker * `init()`. 109*523fa7a6SAndroid Build Coastguard Worker */ destroy(ET_UNUSED DelegateHandle * handle)110*523fa7a6SAndroid Build Coastguard Worker virtual void destroy(ET_UNUSED DelegateHandle* handle) const {} 111*523fa7a6SAndroid Build Coastguard Worker }; 112*523fa7a6SAndroid Build Coastguard Worker 113*523fa7a6SAndroid Build Coastguard Worker /** 114*523fa7a6SAndroid Build Coastguard Worker * Returns the corresponding object pointer for a given string name. 115*523fa7a6SAndroid Build Coastguard Worker * The mapping is populated using register_backend method. 116*523fa7a6SAndroid Build Coastguard Worker * 117*523fa7a6SAndroid Build Coastguard Worker * @param[in] name Name of the user-defined backend delegate. 118*523fa7a6SAndroid Build Coastguard Worker * @retval Pointer to the appropriate object that implements BackendInterface. 119*523fa7a6SAndroid Build Coastguard Worker * Nullptr if it can't find anything with the given name. 120*523fa7a6SAndroid Build Coastguard Worker */ 121*523fa7a6SAndroid Build Coastguard Worker BackendInterface* get_backend_class(const char* name); 122*523fa7a6SAndroid Build Coastguard Worker 123*523fa7a6SAndroid Build Coastguard Worker /** 124*523fa7a6SAndroid Build Coastguard Worker * A named instance of a backend. 125*523fa7a6SAndroid Build Coastguard Worker */ 126*523fa7a6SAndroid Build Coastguard Worker struct Backend { 127*523fa7a6SAndroid Build Coastguard Worker /// The name of the backend. Must match the string used in the PTE file. 128*523fa7a6SAndroid Build Coastguard Worker const char* name; 129*523fa7a6SAndroid Build Coastguard Worker /// The instance of the backend to use when loading and executing programs. 130*523fa7a6SAndroid Build Coastguard Worker BackendInterface* backend; 131*523fa7a6SAndroid Build Coastguard Worker }; 132*523fa7a6SAndroid Build Coastguard Worker 133*523fa7a6SAndroid Build Coastguard Worker /** 134*523fa7a6SAndroid Build Coastguard Worker * Registers the Backend object (i.e. string name and BackendInterface pair) so 135*523fa7a6SAndroid Build Coastguard Worker * that it could be called via the name during the runtime. 136*523fa7a6SAndroid Build Coastguard Worker * 137*523fa7a6SAndroid Build Coastguard Worker * @param[in] backend Backend object 138*523fa7a6SAndroid Build Coastguard Worker * @retval Error code representing whether registration was successful. 139*523fa7a6SAndroid Build Coastguard Worker */ 140*523fa7a6SAndroid Build Coastguard Worker ET_NODISCARD Error register_backend(const Backend& backend); 141*523fa7a6SAndroid Build Coastguard Worker 142*523fa7a6SAndroid Build Coastguard Worker } // namespace runtime 143*523fa7a6SAndroid Build Coastguard Worker } // namespace executorch 144*523fa7a6SAndroid Build Coastguard Worker 145*523fa7a6SAndroid Build Coastguard Worker namespace torch { 146*523fa7a6SAndroid Build Coastguard Worker namespace executor { 147*523fa7a6SAndroid Build Coastguard Worker // TODO(T197294990): Remove these deprecated aliases once all users have moved 148*523fa7a6SAndroid Build Coastguard Worker // to the new `::executorch` namespaces. 149*523fa7a6SAndroid Build Coastguard Worker using ::executorch::runtime::Backend; 150*523fa7a6SAndroid Build Coastguard Worker using ::executorch::runtime::CompileSpec; 151*523fa7a6SAndroid Build Coastguard Worker using ::executorch::runtime::DelegateHandle; 152*523fa7a6SAndroid Build Coastguard Worker using ::executorch::runtime::get_backend_class; 153*523fa7a6SAndroid Build Coastguard Worker using ::executorch::runtime::register_backend; 154*523fa7a6SAndroid Build Coastguard Worker using ::executorch::runtime::SizedBuffer; 155*523fa7a6SAndroid Build Coastguard Worker using PyTorchBackendInterface = ::executorch::runtime::BackendInterface; 156*523fa7a6SAndroid Build Coastguard Worker } // namespace executor 157*523fa7a6SAndroid Build Coastguard Worker } // namespace torch 158