已合并
aoti_load_package接口实现 #35687
qiaoyaodan创建于 5月14日
aoti_load_package接口实现 #35687
已合并
共 5 个文件变更+218-13
| @@ -284,11 +284,14 @@ def copy_hpp(): | |||
| 284 | "third_party/acl/inc/*/*/*.h", | 284 | "third_party/acl/inc/*/*/*.h", |
| 285 | "third_party/hccl/inc/*/*.h", | 285 | "third_party/hccl/inc/*/*.h", |
| 286 | ] | 286 | ] |
| 287 | - glob_header_files = [] | 287 | + glob_header_files_old = [] |
| 288 | for regex_pattern in header_files: | 288 | for regex_pattern in header_files: |
| 289 | - glob_header_files += glob.glob( | 289 | + glob_header_files_old += glob.glob( |
| 290 | os.path.join(BASE_DIR, regex_pattern), recursive=True | 290 | os.path.join(BASE_DIR, regex_pattern), recursive=True |
| 291 | ) | 291 | ) |
| 292 | + | ||
| 293 | + suffixes = ("/torch_npu/csrc/inductor/aoti_package/pybind.h", "/torch_npu/csrc/inductor/aoti_runner/pybind.h") | ||
| 294 | + glob_header_files = [path for path in glob_header_files_old if not path.endswith(suffixes)] | ||
| 292 | 295 | ||
| 293 | for src in glob_header_files: | 296 | for src in glob_header_files: |
| 294 | dst = os.path.join( | 297 | dst = os.path.join( |
| @@ -0,0 +1,70 @@ | |||
| 1 | + | ||
| 2 | + | ||
Z | |||
| 3 | + | ||
| 4 | + | ||
| 5 | + | ||
| 6 | + | ||
| 7 | + | ||
| 8 | + | ||
| 9 | + | ||
| 10 | + | ||
| 11 | + | ||
| 12 | +namespace torch::inductor { | ||
| 13 | + | ||
| 14 | +class AOTIModelPackageLoaderPybind : public AOTIModelPackageLoader { | ||
| 15 | + public: | ||
| 16 | + AOTIModelPackageLoaderPybind( | ||
| 17 | + const std::string& model_package_path, | ||
| 18 | + const std::string& model_name, | ||
| 19 | + const bool run_single_threaded) | ||
| 20 | + : AOTIModelPackageLoader( | ||
| 21 | + model_package_path, | ||
| 22 | + model_name, | ||
| 23 | + run_single_threaded) {} | ||
| 24 | + | ||
| 25 | + py::list boxed_run(py::list& inputs, void* stream_handle = nullptr) { | ||
| 26 | + std::vector<at::Tensor> input_tensors; | ||
| 27 | + input_tensors.reserve(inputs.size()); | ||
| 28 | + for (auto& item : inputs) { | ||
| 29 | + input_tensors.emplace_back(py::cast<at::Tensor>(item)); | ||
| 30 | + } | ||
| 31 | + // Explicitly clear the passed-in Python list | ||
| 32 | + inputs.attr("clear")(); | ||
| 33 | + | ||
| 34 | + std::vector<at::Tensor> result_tensors = AOTIModelPackageLoader::boxed_run( | ||
| 35 | + std::move(input_tensors), stream_handle); | ||
| 36 | + | ||
| 37 | + py::list outputs; | ||
| 38 | + for (const auto& tensor : result_tensors) { | ||
| 39 | + outputs.append( | ||
| 40 | + py::reinterpret_steal<py::object>(THPVariable_Wrap(tensor))); | ||
| 41 | + } | ||
| 42 | + return outputs; | ||
| 43 | + } | ||
| 44 | +}; | ||
| 45 | + | ||
| 46 | +void initAOTIPackageBindings(PyObject* module) { | ||
| 47 | + auto rootModule = py::handle(module).cast<py::module>(); | ||
| 48 | + auto m = rootModule.def_submodule("_aoti"); | ||
| 49 | + | ||
| 50 | + py::class_<AOTIModelPackageLoaderPybind>(m, "AOTIModelPackageLoader") | ||
| 51 | + .def(py::init<const std::string&, const std::string&, const bool>()) | ||
| 52 | + .def("get_metadata", &AOTIModelPackageLoaderPybind::get_metadata) | ||
| 53 | + .def( | ||
| 54 | + "run", | ||
| 55 | + &AOTIModelPackageLoaderPybind::run, | ||
| 56 | + py::arg("inputs"), | ||
| 57 | + py::arg("stream_handle") = nullptr) | ||
| 58 | + .def( | ||
| 59 | + "boxed_run", | ||
| 60 | + &AOTIModelPackageLoaderPybind::boxed_run, | ||
| 61 | + py::arg("inputs"), | ||
| 62 | + py::arg("stream_handle") = nullptr) | ||
| 63 | + .def("get_call_spec", &AOTIModelPackageLoaderPybind::get_call_spec) | ||
| 64 | + .def("load_constants", &AOTIModelPackageLoaderPybind::load_constants) | ||
| 65 | + .def( | ||
| 66 | + "get_constant_fqns", | ||
| 67 | + &AOTIModelPackageLoaderPybind::get_constant_fqns); | ||
| 68 | +} | ||
| 69 | +} // namespace torch::inductor | ||
| 70 | + | ||
| @@ -0,0 +1,18 @@ | |||
| 1 | + | ||
| 2 | + | ||
| 3 | + | ||
| 4 | + | ||
| 5 | + | ||
| 6 | +namespace torch::inductor { | ||
| 7 | +class TORCH_API AOTIModelContainerRunnerCpu : public AOTIModelContainerRunner { | ||
| 8 | + public: | ||
| 9 | + AOTIModelContainerRunnerCpu( | ||
| 10 | + const std::string& model_so_path, | ||
| 11 | + size_t num_models = 1, | ||
| 12 | + const bool run_single_threaded = false); | ||
| 13 | + | ||
| 14 | + ~AOTIModelContainerRunnerCpu() override; | ||
| 15 | +}; | ||
| 16 | + | ||
| 17 | +} // namespace torch::inductor | ||
| 18 | + | ||
| @@ -0,0 +1,93 @@ | |||
| 1 | + | ||
| 2 | + | ||
| 3 | + | ||
| 4 | + | ||
| 5 | + | ||
| 6 | + | ||
| 7 | + | ||
| 8 | + | ||
| 9 | + | ||
| 10 | + | ||
| 11 | + | ||
| 12 | +namespace torch::inductor { | ||
| 13 | + | ||
| 14 | +void initAOTIRunnerBindings(PyObject* module) { | ||
| 15 | + auto rootModule = py::handle(module).cast<py::module>(); | ||
| 16 | + auto m = rootModule.def_submodule("_aoti"); | ||
| 17 | + | ||
| 18 | + py::class_<AOTIModelContainerRunnerCpu>(m, "AOTIModelContainerRunnerCpu") | ||
| 19 | + .def(py::init<const std::string&, int>()) | ||
| 20 | + .def( | ||
| 21 | + "run", | ||
| 22 | + &AOTIModelContainerRunnerCpu::run, | ||
| 23 | + py::arg("inputs"), | ||
| 24 | + py::arg("stream_handle") = nullptr) | ||
| 25 | + .def("get_call_spec", &AOTIModelContainerRunnerCpu::get_call_spec) | ||
| 26 | + .def( | ||
| 27 | + "get_constant_names_to_original_fqns", | ||
| 28 | + &AOTIModelContainerRunnerCpu::getConstantNamesToOriginalFQNs) | ||
| 29 | + .def( | ||
| 30 | + "get_constant_names_to_dtypes", | ||
| 31 | + &AOTIModelContainerRunnerCpu::getConstantNamesToDtypes) | ||
| 32 | + .def( | ||
| 33 | + "update_constant_buffer", | ||
| 34 | + static_cast<void (AOTIModelContainerRunnerCpu::*)( | ||
| 35 | + std::unordered_map<std::string, at::Tensor>&, bool, bool)>( | ||
| 36 | + &AOTIModelContainerRunnerCpu::update_constant_buffer)); | ||
| 37 | + | ||
| 38 | + | ||
| 39 | + py::class_<AOTIModelContainerRunnerNpu>(m, "AOTIModelContainerRunnerNpu") | ||
| 40 | + .def(py::init<const std::string&, int>()) | ||
| 41 | + .def(py::init<const std::string&, int, const std::string&>()) | ||
| 42 | + .def(py::init< | ||
| 43 | + const std::string&, | ||
| 44 | + int, | ||
| 45 | + const std::string&, | ||
| 46 | + const std::string&>()) | ||
| 47 | + .def( | ||
| 48 | + "run", | ||
| 49 | + &AOTIModelContainerRunnerNpu::run, | ||
| 50 | + py::arg("inputs"), | ||
| 51 | + py::arg("stream_handle") = nullptr) | ||
| 52 | + .def("get_call_spec", &AOTIModelContainerRunnerNpu::get_call_spec) | ||
| 53 | + .def( | ||
| 54 | + "get_constant_names_to_original_fqns", | ||
| 55 | + &AOTIModelContainerRunnerNpu::getConstantNamesToOriginalFQNs) | ||
| 56 | + .def( | ||
| 57 | + "get_constant_names_to_dtypes", | ||
| 58 | + &AOTIModelContainerRunnerNpu::getConstantNamesToDtypes) | ||
| 59 | + .def( | ||
| 60 | + "update_constant_buffer", | ||
| 61 | + static_cast<void (AOTIModelContainerRunnerNpu::*)( | ||
| 62 | + std::unordered_map<std::string, at::Tensor>&, bool, bool)>( | ||
| 63 | + &AOTIModelContainerRunnerNpu::update_constant_buffer)); | ||
| 64 | + | ||
| 65 | + | ||
| 66 | + m.def( | ||
| 67 | + "unsafe_alloc_void_ptrs_from_tensors", | ||
| 68 | + [](const std::vector<at::Tensor>& tensors) { | ||
| 69 | + std::vector<AtenTensorHandle> handles = | ||
| 70 | + torch::aot_inductor::unsafe_alloc_new_handles_from_tensors(tensors); | ||
| 71 | + std::vector<void*> result( | ||
| 72 | + reinterpret_cast<void**>(handles.data()), | ||
| 73 | + reinterpret_cast<void**>(handles.data()) + handles.size()); | ||
| 74 | + return result; | ||
| 75 | + }); | ||
| 76 | + m.def("unsafe_alloc_void_ptr_from_tensor", [](at::Tensor& tensor) { | ||
| 77 | + return reinterpret_cast<void*>( | ||
| 78 | + torch::aot_inductor::new_tensor_handle(std::move(tensor))); | ||
| 79 | + }); | ||
| 80 | + m.def( | ||
| 81 | + "alloc_tensors_by_stealing_from_void_ptrs", | ||
| 82 | + [](std::vector<void*>& raw_handles) { | ||
| 83 | + return torch::aot_inductor::alloc_tensors_by_stealing_from_handles( | ||
| 84 | + reinterpret_cast<AtenTensorHandle*>(raw_handles.data()), | ||
| 85 | + raw_handles.size()); | ||
| 86 | + }); | ||
| 87 | + m.def("alloc_tensor_by_stealing_from_void_ptr", [](void* raw_handle) { | ||
| 88 | + return *torch::aot_inductor::tensor_handle_to_tensor_pointer( | ||
| 89 | + reinterpret_cast<AtenTensorHandle>(raw_handle)); | ||
| 90 | + }); | ||
| 91 | +} | ||
| 92 | +} // namespace torch::inductor | ||
| 93 | + | ||
| @@ -87,25 +87,46 @@ using ConstantMap = std::unordered_map<std::string, RAIIAtenTensorHandle>; | |||
| 87 | // Update the list here if more devices are supported in the future | 87 | // Update the list here if more devices are supported in the future |
| 88 | inline void parse_device_str(const std::string& device_str, int32_t& device_type, int32_t& device_idx) | 88 | inline void parse_device_str(const std::string& device_str, int32_t& device_type, int32_t& device_idx) |
| 89 | { | 89 | { |
| 90 | - std::regex re("(cpu|npu)(:([0-9]+))?"); | 90 | + if (device_str.empty()) { |
| 91 | - std::smatch sm; | 91 | + AOTI_RUNTIME_CHECK(false, "Invalid device: " + device_str); |
| 92 | - bool matched = std::regex_match(device_str, sm, re); | 92 | + } |
| 93 | - AOTI_RUNTIME_CHECK(matched, "Invalid device: " + device_str); | ||
| 94 | 93 | ||
| 95 | - if (sm[1].str() == "cpu") { | 94 | + size_t colon_pos = device_str.find(':'); |
| 95 | + std::string device_type_str; | ||
| 96 | + if (colon_pos == std::string::npos) { | ||
| 97 | + device_type_str = device_str; | ||
| 98 | + } else { | ||
| 99 | + device_type_str = device_str.substr(0, colon_pos); | ||
| 100 | + } | ||
| 101 | + | ||
| 102 | + if (device_type_str == "cpu") { | ||
| 96 | device_type = aoti_torch_device_type_cpu(); | 103 | device_type = aoti_torch_device_type_cpu(); |
| 97 | 104 | ||
| 98 | - } else if (sm[1].str() == "npu") { | 105 | + } else if (device_type_str == "npu") { |
| 99 | device_type = aoti_torch_device_type_npu(); | 106 | device_type = aoti_torch_device_type_npu(); |
| 100 | 107 | ||
| 101 | } else { | 108 | } else { |
| 102 | AOTI_RUNTIME_CHECK(false, "Invalid device: " + device_str); | 109 | AOTI_RUNTIME_CHECK(false, "Invalid device: " + device_str); |
| 103 | } | 110 | } |
| 104 | - const size_t default_sm = 3; | 111 | + |
| 105 | - if (sm[default_sm].matched) { | 112 | + device_idx = -1; |
| 106 | - device_idx = stoi(sm[default_sm].str()); | 113 | + if (colon_pos != std::string::npos) { |
| 107 | - } else { | 114 | + std::string index_str = device_str.substr(colon_pos + 1); |
| 108 | - device_idx = -1; | 115 | + if (index_str.empty()) { |
| 116 | + AOTI_RUNTIME_CHECK(false, "Invalid device: " + device_str); | ||
| 117 | + } | ||
| 118 | + for (char c : index_str) { | ||
| 119 | + if (!std::isdigit(c)) { | ||
| 120 | + AOTI_RUNTIME_CHECK(false, "Invalid device: " + device_str); | ||
| 121 | + } | ||
| 122 | + } | ||
| 123 | + try { | ||
| 124 | + device_idx = std::stoi(index_str); | ||
| 125 | + } catch (const std::out_of_range& e) { | ||
| 126 | + AOTI_RUNTIME_CHECK(false, "Invalid device: " + device_str); | ||
| 127 | + } catch (const std::invalid_argument& e) { | ||
| 128 | + AOTI_RUNTIME_CHECK(false, "Invalid device: " + device_str); | ||
| 129 | + } | ||
| 109 | } | 130 | } |
| 110 | } | 131 | } |
| 111 | 132 | ||
完善aoti的测试用例,用来看护该特性