Skip to content

Support bare-metal Windows #3735

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 29 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
bf04d28
Use glob ignore
hans00 May 24, 2024
e58042c
Support Windows
hans00 May 24, 2024
969b612
Fix unknown type
hans00 May 25, 2024
e9f162f
Add ignoring files
hans00 May 25, 2024
00845ea
Fix build for QNN
hans00 May 25, 2024
f4a52a5
Correct impl
hans00 May 25, 2024
b2a056a
Fix not found symbol on Windows DLL
hans00 May 25, 2024
91f4551
Just warning once
hans00 May 29, 2024
3c80ec4
Fix build for QNN
hans00 May 29, 2024
86e2bc6
Force export `QnnExecuTorchAllocCustomMem`, `QnnExecuTorchFreeCustomMem`
hans00 May 29, 2024
e8192ad
Reduce dup-compile for custom kernels
hans00 May 27, 2024
e99fc73
Use visibility instead dllexport
hans00 May 29, 2024
4b6189f
Fix QNN for Windows
hans00 May 29, 2024
b512236
Support Windows platform
hans00 May 29, 2024
f41acfd
File loader support Windows API
hans00 May 29, 2024
f0a8b03
Make cmake `LIB_xxx` point to correct lib path
hans00 May 31, 2024
157d275
Merge branch 'pytorch:main' into windows
hans00 May 31, 2024
49add79
Move shared memory management to platform implement
hans00 Jun 1, 2024
a45e9e3
Merge branch 'pytorch:main' into windows
hans00 Jun 1, 2024
ba90d0b
Revert "Move shared memory management to platform implement"
hans00 Jun 2, 2024
06a4429
Fix time release
hans00 Jun 2, 2024
b0c81d4
Merge branch 'pytorch:main' into windows
hans00 Jun 14, 2024
7ed8af1
Merge branch 'main' into windows
hans00 Sep 23, 2024
b013a53
Fix build
hans00 Sep 23, 2024
5b87e50
Fix shared segment for MinGW
hans00 Sep 23, 2024
25d7751
Merge `runtime/platform/default/Windows.cpp` into `runtime/platform/d…
hans00 Sep 23, 2024
304734d
Support cross-compile
hans00 Sep 27, 2024
93695c4
Support cross-compile for macOS
hans00 Sep 28, 2024
2cbb252
Correct arg value when cross compile macOS
hans00 Sep 28, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
.hypothesis
buck-out/
cmake-out/
cmake-android-out/
cmake-out-android/
cmake-ios-out/
cmake-*-out/
cmake-out-*/
ethos-u-scratch/
executorch.egg-info
pip-out/
__pycache__/
.python-version

# Any exported models and profiling outputs
*.pte
Expand Down
1 change: 1 addition & 0 deletions backends/qualcomm/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
*_generated.h
10 changes: 6 additions & 4 deletions backends/qualcomm/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -183,9 +183,11 @@ target_link_libraries(
qnn_executorch_backend PRIVATE qnn_executorch_header qnn_schema qnn_manager
executorch_no_prim_ops qcir_utils extension_tensor
)
set_target_properties(
qnn_executorch_backend PROPERTIES LINK_FLAGS "-Wl,-rpath='$ORIGIN'"
)
if (NOT CMAKE_SYSTEM_NAME STREQUAL "Windows")
set_target_properties(
qnn_executorch_backend PROPERTIES LINK_FLAGS "-Wl,-rpath='$ORIGIN'"
)
endif()
target_link_libraries(utils PRIVATE qnn_executorch_logging)
target_link_libraries(
shared_buffer PRIVATE qnn_executorch_logging ${CMAKE_DL_LIBS}
Expand Down Expand Up @@ -221,7 +223,7 @@ add_subdirectory(
install(TARGETS qnn_executorch_backend DESTINATION lib)

# QNN pybind
if(${CMAKE_SYSTEM_PROCESSOR} MATCHES "x86_64")
if(EXECUTORCH_BUILD_PYBIND)
add_subdirectory(
${EXECUTORCH_SOURCE_DIR}/third-party/pybind11
${CMAKE_CURRENT_BINARY_DIR}/pybind11
Expand Down
2 changes: 1 addition & 1 deletion backends/qualcomm/aot/ir/qcir_utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ flatbuffers::Offset<qcir::QuantizeParam> ToQuantizeParam(
size_t len = param.axisScaleOffsetEncoding.numScaleOffsets;
axis = param.axisScaleOffsetEncoding.axis;
data.reserve(len);
for (uint i = 0; i < len; ++i) {
for (size_t i = 0; i < len; ++i) {
data.emplace_back(qcir::ScaleOffset(
param.axisScaleOffsetEncoding.scaleOffset[i].scale,
param.axisScaleOffsetEncoding.scaleOffset[i].offset));
Expand Down
3 changes: 3 additions & 0 deletions backends/qualcomm/aot/python/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,6 @@ target_sources(
PyQnnWrapperAdaptor PUBLIC ${CMAKE_CURRENT_LIST_DIR}/PyQnnWrapperAdaptor.cpp
${CMAKE_CURRENT_LIST_DIR}/PyQnnWrapperAdaptor.h
)

target_compile_options(PyQnnManagerAdaptor PRIVATE -fexceptions)
target_compile_options(PyQnnWrapperAdaptor PRIVATE -fexceptions)
11 changes: 7 additions & 4 deletions backends/qualcomm/runtime/QnnManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -528,24 +528,27 @@ Error QnnManager::Compile(
} // namespace qnn
} // namespace executor
} // namespace torch
void* QnnExecuTorchAllocCustomMem(size_t bytes, size_t alignment) {

#define EXPORT __attribute__((visibility("default")))

EXPORT void* QnnExecuTorchAllocCustomMem(size_t bytes, size_t alignment) {
void* buffer_ptr =
torch::executor::qnn::SharedBuffer::GetSharedBufferManager().AllocMem(
bytes, alignment);
return buffer_ptr;
}

void QnnExecuTorchFreeCustomMem(void* buffer_ptr) {
EXPORT void QnnExecuTorchFreeCustomMem(void* buffer_ptr) {
torch::executor::qnn::SharedBuffer::GetSharedBufferManager().FreeMem(
buffer_ptr);
}

void QnnExecuTorchAddCustomMemTensorAddr(void* tensor_addr, void* custom_mem) {
EXPORT void QnnExecuTorchAddCustomMemTensorAddr(void* tensor_addr, void* custom_mem) {
torch::executor::qnn::SharedBuffer::GetSharedBufferManager()
.AddCusomMemTensorAddr(tensor_addr, custom_mem);
}

void QnnExecuTorchAddCustomMemTensorInfo(const CustomMemTensorInfo& info) {
EXPORT void QnnExecuTorchAddCustomMemTensorInfo(const CustomMemTensorInfo& info) {
torch::executor::qnn::SharedBuffer::GetSharedBufferManager()
.AddCusomMemTensorInfo(info);
}
6 changes: 6 additions & 0 deletions backends/qualcomm/runtime/QnnManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,9 +80,15 @@ class QnnManager {
private:
Error LoadQnnLibrary();

#ifdef _WIN32
static constexpr const char* htp_library_name_ = "QnnHtp.dll";
static constexpr const char* gpu_library_name_ = "QnnGpu.dll";
static constexpr const char* dsp_library_name_ = "QnnDsp.dll";
#else
static constexpr const char* htp_library_name_ = "libQnnHtp.so";
static constexpr const char* gpu_library_name_ = "libQnnGpu.so";
static constexpr const char* dsp_library_name_ = "libQnnDsp.so";
#endif

QnnExecuTorchContextBinary qnn_context_blob_;
std::unique_ptr<BackendConfigParameters> backend_params_ptr_;
Expand Down
11 changes: 11 additions & 0 deletions backends/qualcomm/runtime/SharedBuffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree.
*/
#ifdef __ANDROID__
#include <dlfcn.h>
#endif
#include <executorch/backends/qualcomm/runtime/Logging.h>
#include <executorch/backends/qualcomm/runtime/SharedBuffer.h>

Expand Down Expand Up @@ -158,6 +160,10 @@ bool SharedBuffer::IsAllocated(void* buf) {
}

Error SharedBuffer::Load() {
#ifndef __ANDROID__
QNN_EXECUTORCH_LOG_WARN("Shared buffer is not supported on this platform.");
return Error::Ok;
#else
// On Android, 32-bit and 64-bit libcdsprpc.so can be found at /vendor/lib/
// and /vendor/lib64/ respectively.
lib_cdsp_rpc_ = dlopen("libcdsprpc.so", RTLD_NOW | RTLD_LOCAL);
Expand All @@ -180,6 +186,7 @@ Error SharedBuffer::Load() {
return Error::Internal;
}
return Error::Ok;
#endif
}

void SharedBuffer::AddCusomMemTensorAddr(void* tensor_addr, void* custom_mem) {
Expand All @@ -192,12 +199,16 @@ void SharedBuffer::AddCusomMemTensorInfo(const CustomMemTensorInfo& info) {
}

Error SharedBuffer::UnLoad() {
#ifndef __ANDROID__
return Error::Ok;
#else
if (dlclose(lib_cdsp_rpc_) != 0) {
QNN_EXECUTORCH_LOG_ERROR(
"Unable to close shared buffer. dlerror(): %s", dlerror());
return Error::Internal;
};
return Error::Ok;
#endif
}
} // namespace qnn
} // namespace executor
Expand Down
2 changes: 1 addition & 1 deletion backends/qualcomm/runtime/SharedBuffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ class SharedBuffer final {

// Pointer to the dlopen'd libcdsprpc.so shared library which contains
// rpcmem_alloc, rpcmem_free, rpcmem_to_fd APIs
void* lib_cdsp_rpc_;
[[maybe_unused]] void* lib_cdsp_rpc_;
// Function pointer to rpcmem_alloc
RpcMemAllocFn_t rpc_mem_alloc_;
// Function pointer to rpcmem_free
Expand Down
8 changes: 8 additions & 0 deletions backends/qualcomm/runtime/Utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,11 @@
*/
#include <executorch/backends/qualcomm/runtime/Logging.h>
#include <executorch/backends/qualcomm/runtime/Utils.h>
#ifdef _WIN32
#include <direct.h>
#else
#include <sys/stat.h>
#endif
namespace torch {
namespace executor {
namespace qnn {
Expand All @@ -24,7 +28,11 @@ void CreateDirectory(const std::string& path) {
return;
}
CreateDirectory(subdir);
#ifdef _WIN32
int mkdir_err = _mkdir(subdir.c_str());
#else
int mkdir_err = mkdir(subdir.c_str(), S_IRWXU | S_IRWXG | S_IRWXO);
#endif
if (mkdir_err != 0 && errno != EEXIST) {
std::string err_msg = "Failed to create " + subdir + " folder\n";
QNN_EXECUTORCH_LOG_ERROR(err_msg.c_str());
Expand Down
11 changes: 10 additions & 1 deletion backends/qualcomm/runtime/backends/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,17 @@ target_sources(
)

# qnn_device
set(BACKEND_ARCH ${CMAKE_SYSTEM_PROCESSOR})
if(BACKEND_ARCH STREQUAL "arm64" OR BACKEND_ARCH STREQUAL "aarch64" OR
BACKEND_ARCH STREQUAL "arm64-v8a")
set(BACKEND_ARCH "aarch64")
elseif(BACKEND_ARCH STREQUAL "x86_64")
set(BACKEND_ARCH "x86_64")
else()
message(FATAL_ERROR "Unsupported architecture: ${BACKEND_ARCH}")
endif()
set(HOST_ARCHITECTURE
${CMAKE_CURRENT_LIST_DIR}/htpbackend/${CMAKE_SYSTEM_PROCESSOR}
${CMAKE_CURRENT_LIST_DIR}/htpbackend/${BACKEND_ARCH}
)

target_sources(
Expand Down
4 changes: 4 additions & 0 deletions backends/qualcomm/runtime/backends/QnnBackendCache.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,11 @@ class QnnBackendCache {

QnnExecuTorchContextBinary qnn_context_blob_;
QnnSystemContext_Handle_t sys_context_handle_{nullptr};
#ifdef _WIN32
QnnSystemImplementation qnn_sys_impl_{ "QnnSystem.dll" };
#else
QnnSystemImplementation qnn_sys_impl_{"libQnnSystem.so"};
#endif
std::string graph_name_;
std::vector<Qnn_Tensor_t> input_tensor_structs_;
std::vector<Qnn_Tensor_t> output_tensor_structs_;
Expand Down
4 changes: 4 additions & 0 deletions backends/qualcomm/runtime/backends/QnnBackendFactory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,12 @@ std::unique_ptr<BackendConfigParameters> QnnBackendFactory::Create(
const std::string skel_library_dir =
htp_options->skel_library_dir()->str();
if (!skel_library_dir.empty()) {
#ifdef _WIN32
_putenv_s("ADSP_LIBRARY_PATH", skel_library_dir.c_str());
#else
setenv(
"ADSP_LIBRARY_PATH", skel_library_dir.c_str(), /*overwrite=*/1);
#endif
}
QNN_EXECUTORCH_LOG_INFO(
"skel_library_dir: %s", skel_library_dir.c_str());
Expand Down
5 changes: 5 additions & 0 deletions backends/qualcomm/runtime/backends/QnnFunctionInterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@
*/
#pragma once

// Dummy fix `interface` definition in Windows
#if defined(__WIN32__) && defined(interface)
#undef interface
#endif

#include "QnnInterface.h"
#include "Saver/QnnSaver.h"

Expand Down
52 changes: 52 additions & 0 deletions backends/qualcomm/runtime/backends/QnnImplementation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree.
*/
#ifdef _WIN32
#include <windows.h>
#else
#include <dlfcn.h>
#endif
#include <executorch/backends/qualcomm/runtime/backends/QnnImplementation.h>

#include "QnnInterface.h"
Expand All @@ -14,7 +18,11 @@ namespace executor {
namespace qnn {
template <typename Fn>
Fn loadQnnFunction(void* handle, const char* function_name) {
#ifdef _WIN32
return reinterpret_cast<Fn>(GetProcAddress(reinterpret_cast<HMODULE>(handle), function_name));
#else
return reinterpret_cast<Fn>(dlsym(handle, function_name)); // NOLINT
#endif
}

Error QnnImplementation::InitBackend(
Expand Down Expand Up @@ -54,13 +62,24 @@ Error QnnImplementation::StartBackend(
const std::string& lib_path,
const QnnSaver_Config_t** saver_config) {
Qnn_ErrorHandle_t error = QNN_SUCCESS;
#ifdef _WIN32
void* lib_handle = LoadLibrary(lib_path.c_str());
#else
void* lib_handle = dlopen(lib_path.c_str(), RTLD_NOW | RTLD_GLOBAL);
#endif

if (lib_handle == nullptr) {
#ifdef _WIN32
QNN_EXECUTORCH_LOG_ERROR(
"Cannot Open QNN library %s, with error: %d",
lib_path.c_str(),
GetLastError());
#else
QNN_EXECUTORCH_LOG_ERROR(
"Cannot Open QNN library %s, with error: %s",
lib_path.c_str(),
dlerror());
#endif
return Error::Internal;
}

Expand All @@ -72,7 +91,11 @@ Error QnnImplementation::StartBackend(
QNN_EXECUTORCH_LOG_ERROR(
"QnnImplementation::Load Cannot load symbol "
"QnnInterface_getProviders : %s",
#ifdef _WIN32
GetLastError());
#else
dlerror());
#endif
return Error::Internal;
}

Expand Down Expand Up @@ -120,13 +143,22 @@ Error QnnImplementation::StartBackend(
if (loaded_lib_handle_.count(backend_id) > 0) {
QNN_EXECUTORCH_LOG_WARN("closing %pK...", loaded_lib_handle_[backend_id]);

#ifdef _WIN32
if (FreeLibrary(reinterpret_cast<HMODULE>(loaded_lib_handle_[backend_id])) == 0) {
QNN_EXECUTORCH_LOG_WARN(
"Sadly, fail to close %pK with error %d",
loaded_lib_handle_[backend_id],
GetLastError());
}
#else
int dlclose_error = dlclose(loaded_lib_handle_[backend_id]);
if (dlclose_error != 0) {
QNN_EXECUTORCH_LOG_WARN(
"Sadly, fail to close %pK with error %s",
loaded_lib_handle_[backend_id],
dlerror());
}
#endif
}
loaded_lib_handle_[backend_id] = lib_handle;

Expand All @@ -138,6 +170,15 @@ Error QnnImplementation::StartBackend(
lib_path_to_backend_id_.erase(lib_path);
loaded_backend_.erase(backend_id);

#ifdef _WIN32
if (FreeLibrary(reinterpret_cast<HMODULE>(loaded_lib_handle_[backend_id])) == 0) {
QNN_EXECUTORCH_LOG_WARN(
"fail to close %pK after backend-init "
"failure, with error %d",
loaded_lib_handle_[backend_id],
GetLastError());
}
#else
int dlclose_error = dlclose(loaded_lib_handle_[backend_id]);
if (dlclose_error != 0) {
QNN_EXECUTORCH_LOG_WARN(
Expand All @@ -146,6 +187,7 @@ Error QnnImplementation::StartBackend(
loaded_lib_handle_[backend_id],
dlerror());
}
#endif

loaded_lib_handle_.erase(backend_id);
return be_init_st;
Expand All @@ -160,12 +202,22 @@ Error QnnImplementation::TerminateAllBackends() {
loaded_backend_.clear();

for (auto& it : loaded_lib_handle_) {
#ifdef _WIN32
if (FreeLibrary(reinterpret_cast<HMODULE>(it.second)) == 0) {
QNN_EXECUTORCH_LOG_ERROR(
"Fail to close QNN backend %d with error %d",
it.first,
GetLastError());
ret_status = Error::Internal;
}
#else
int dlclose_error = dlclose(it.second);
if (dlclose_error != 0) {
QNN_EXECUTORCH_LOG_ERROR(
"Fail to close QNN backend %d with error %s", it.first, dlerror());
ret_status = Error::Internal;
}
#endif
}
loaded_lib_handle_.clear();
lib_path_to_backend_id_.clear();
Expand Down
Loading