Skip to content

Commit

Permalink
[OPENCL][ADRENO] Introduce Qualcomm extension support (#17519)
Browse files Browse the repository at this point in the history
Introduce qualcomm extension support

"cl_qcom_perf_hint", "cl_qcom_priority_hint" extn support added over
workspace interface.

OpenCL version will be picked up from SDK headers. CI fixes for build
without Adreno OpenCL SDK.
Entensions are activated based on its availability in SDK.

New workspace API "SetNativePtr" defined that releases existing cl_mem
and creates new mem object backed by given host ptr.

Works for cl_qcom_ion_host_ptr,
cl_qcom_android_ahardwarebuffer_host_ptr,
cl_qcom_android_native_buffer_host_ptr, cl_qcom_dmabuf_host_ptr and
cl_qcom_ion_host_ptr.

The responsibility of preparing the host_ptr objects is with
application.

Some times the application needs device id for various devices related
information. Use below ref. to get cl_device_id from workspace.

OpenCLWorkspace* workspace = OpenCLWorkspace::Global(); cl_device_id
device_id = workspace->GetCLDeviceID(0);
  • Loading branch information
srkreddy1238 authored Nov 14, 2024
1 parent 370ec6a commit 37bca85
Show file tree
Hide file tree
Showing 9 changed files with 133 additions and 8 deletions.
3 changes: 3 additions & 0 deletions cmake/config.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -483,3 +483,6 @@ SET(CMAKE_VS_PLATFORM_NAME_DEFAULT "x64")

# Set Windows Visual Studio default host (equivalent to -Thost=x64)
SET(CMAKE_VS_PLATFORM_TOOLSET_HOST_ARCHITECTURE "x64")

# Enable Qualcomm OpenCL extension support
set(USE_OPENCL_EXTN_QCOM OFF)
13 changes: 12 additions & 1 deletion cmake/modules/OpenCL.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ if(USE_OPENCL)
"tests/cpp-runtime/opencl/*.cc"
)
add_executable(opencl-cpptest ${OPENCL_TEST_SRCS})
target_link_libraries(opencl-cpptest PRIVATE gtest_main tvm_runtime)
target_link_libraries(opencl-cpptest PRIVATE gtest_main tvm_runtime ${OpenCL_LIBRARIES})
else()
message(STATUS "Couldn't build OpenCL-Gtests")
endif()
Expand All @@ -93,6 +93,17 @@ if(USE_OPENCL)
if(USE_OPENCL_ENABLE_HOST_PTR)
add_definitions(-DOPENCL_ENABLE_HOST_PTR)
endif(USE_OPENCL_ENABLE_HOST_PTR)
if(USE_OPENCL_EXTN_QCOM)
add_definitions(-DUSE_OPENCL_EXTN_QCOM)
find_path(ocl_header cl.h HINTS ${OpenCL_INCLUDE_DIRS} PATH_SUFFIXES CL)
set(OCL_VERSION_HEADER "${ocl_header}/cl.h")
if(EXISTS ${OCL_VERSION_HEADER})
file(READ ${OCL_VERSION_HEADER} ver)
string(REGEX MATCH "CL_TARGET_OPENCL_VERSION ([0-9]*)" _ ${ver})
add_definitions(-DCL_TARGET_OPENCL_VERSION=${CMAKE_MATCH_1})
message(STATUS "Set OpenCL Target version to " ${CMAKE_MATCH_1})
endif()
endif(USE_OPENCL_EXTN_QCOM)
else()
list(APPEND COMPILER_SRCS src/target/opt/build_opencl_off.cc)
endif(USE_OPENCL)
2 changes: 1 addition & 1 deletion cmake/modules/contrib/CLML.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ if(USE_CLML_GRAPH_EXECUTOR)
message(STATUS "Enable OpenCL as fallback to CLML")
file(GLOB RUNTIME_OPENCL_SRCS src/runtime/opencl/*.cc)
list(APPEND RUNTIME_SRCS ${RUNTIME_OPENCL_SRCS})
set(USE_OPENCL ON)
set(USE_OPENCL ${CLML_PATH})
if(USE_OPENCL_ENABLE_HOST_PTR)
add_definitions(-DOPENCL_ENABLE_HOST_PTR)
endif(USE_OPENCL_ENABLE_HOST_PTR)
Expand Down
2 changes: 1 addition & 1 deletion cmake/utils/FindOpenCL.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ macro(find_opencl use_opencl)
endif()

if(__opencl_sdk)
set(OpenCL_INCLUDE_DIRS ${__opencl_sdk}/include)
set(OpenCL_INCLUDE_DIRS ${__opencl_sdk}/include ${__opencl_sdk})
if (CMAKE_FIND_ROOT_PATH_MODE_LIBRARY STREQUAL "ONLY")
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY BOTH)
endif()
Expand Down
14 changes: 13 additions & 1 deletion src/runtime/opencl/opencl_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,17 @@
* files. This also allows us to expose the OpenCL version through
* tvm.runtime.Device.
*/
#if !defined(CL_TARGET_OPENCL_VERSION)
#define CL_TARGET_OPENCL_VERSION 120
#endif

#ifdef __APPLE__
#include <OpenCL/opencl.h>
#else
#include <CL/opencl.h>
#ifdef USE_OPENCL_EXTN_QCOM
#include <CL/cl_ext_qcom.h>
#endif
#endif

#include <memory>
Expand Down Expand Up @@ -254,8 +259,13 @@ class OpenCLWorkspace : public DeviceAPI {
}
// Initialize the device.
void Init(const std::string& type_key, const std::string& device_type,
const std::string& platform_name = "");
const std::string& platform_name = "", cl_context_properties properties[] = nullptr);
virtual void Init() { Init(this->type_key, "gpu"); }
virtual bool Init(cl_context_properties ctx_props[]) {
if (!contexts.empty()) return false;
Init(this->type_key, "gpu", "", ctx_props);
return true;
}
// Check whether the context is OpenCL or not.
virtual bool IsOpenCLDevice(Device dev) { return dev.device_type == kDLOpenCL; }
// get the queue of the device
Expand Down Expand Up @@ -314,6 +324,8 @@ class OpenCLWorkspace : public DeviceAPI {
void* AllocDataSpace(Device dev, int ndim, const int64_t* shape, DLDataType dtype,
Optional<String> mem_scope = NullOpt) final;
void* GetNativePtr(const tvm::runtime::NDArray& narr);
void SetNativePtr(const tvm::runtime::NDArray& narr, void* host_ptr, size_t buf_size);
void SetPerfHint(Device dev, cl_uint perf_hint);
void FreeDataSpace(Device dev, void* ptr) final;
void StreamSync(Device dev, TVMStreamHandle stream) final;
void* AllocWorkspace(Device dev, size_t size, DLDataType type_hint) final;
Expand Down
50 changes: 46 additions & 4 deletions src/runtime/opencl/opencl_device_api.cc
Original file line number Diff line number Diff line change
Expand Up @@ -277,15 +277,57 @@ void* OpenCLWorkspace::GetNativePtr(const tvm::runtime::NDArray& narr) {
return desc->host_ptr;
}

void OpenCLWorkspace::SetNativePtr(const tvm::runtime::NDArray& narr, void* host_ptr,
size_t buf_size) {
cl::BufferDescriptor* desc = static_cast<cl::BufferDescriptor*>(narr.operator->()->data);

this->Init();
if (desc->layout == cl::BufferDescriptor::MemoryLayout::kBuffer1D) {
#ifdef USE_OPENCL_EXTN_QCOM
Device dev = narr.operator->()->device;
cl_device_id device_id = GetCLDeviceID(dev.device_id);
auto platform = device_info[device_id].platform_id;

OPENCL_CALL(clFinish(this->GetQueue(dev)));
if (desc->host_ptr) {
OPENCL_CALL(clEnqueueUnmapMemObject(this->GetQueue(dev), desc->buffer,
reinterpret_cast<void*>(desc->host_ptr), 0, nullptr,
nullptr));
desc->host_ptr = nullptr;
}
OPENCL_CALL(clReleaseMemObject(desc->buffer));

cl_int err_code;
desc->buffer =
clCreateBuffer(this->contexts[platform],
CL_MEM_READ_WRITE | CL_MEM_USE_HOST_PTR | CL_MEM_EXT_HOST_PTR_QCOM, buf_size,
host_ptr, &err_code);
desc->layout = cl::BufferDescriptor::MemoryLayout::kBuffer1D;
OPENCL_CHECK_ERROR(err_code);
#endif
} else {
LOG(FATAL) << "Native Ptr not enabled over image objects";
}
}

void OpenCLWorkspace::SetPerfHint(Device dev, cl_uint perf_hint) {
#ifdef CL_CONTEXT_PERF_HINT_QCOM
cl_device_id device_id = GetCLDeviceID(dev.device_id);
auto platform = device_info[device_id].platform_id;
OPENCL_CALL(clSetPerfHintQCOM(this->contexts[platform], perf_hint));
#endif
}

void OpenCLWorkspace::FreeDataSpace(Device dev, void* ptr) {
// We have to make sure that the memory object is not in the command queue
// for some OpenCL platforms.
OPENCL_CALL(clFinish(this->GetQueue(dev)));

cl::BufferDescriptor* desc = static_cast<cl::BufferDescriptor*>(ptr);
if (desc->host_ptr) {
clEnqueueUnmapMemObject(this->GetQueue(dev), desc->buffer,
reinterpret_cast<void*>(desc->host_ptr), 0, nullptr, nullptr);
OPENCL_CALL(clEnqueueUnmapMemObject(this->GetQueue(dev), desc->buffer,
reinterpret_cast<void*>(desc->host_ptr), 0, nullptr,
nullptr));
}
OPENCL_CALL(clReleaseMemObject(desc->buffer));
delete desc;
Expand Down Expand Up @@ -473,7 +515,7 @@ bool MatchPlatformInfo(cl_platform_id pid, cl_platform_info param_name, std::str
}

void OpenCLWorkspace::Init(const std::string& type_key, const std::string& device_type,
const std::string& platform_name) {
const std::string& platform_name, cl_context_properties ctx_props[]) {
if (initialized_) return;
std::lock_guard<std::mutex> lock(this->mu);
if (initialized_) return;
Expand Down Expand Up @@ -539,7 +581,7 @@ void OpenCLWorkspace::Init(const std::string& type_key, const std::string& devic
for (auto& [platform, devices] : device_map) {
this->platform_ids.push_back(platform);
this->contexts[platform] =
clCreateContext(nullptr, devices.size(), &(devices[0]), nullptr, nullptr, &err_code);
clCreateContext(ctx_props, devices.size(), &(devices[0]), nullptr, nullptr, &err_code);
this->devices.insert(this->devices.end(), devices.begin(), devices.end());
for (size_t i = 0; i < devices.size(); ++i) {
cl_device_id did = devices[i];
Expand Down
5 changes: 5 additions & 0 deletions src/support/libinfo.cc
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,10 @@
#define TVM_INFO_USE_OPENCL_ENABLE_HOST_PTR "NOT-FOUND"
#endif

#ifndef TVM_INFO_USE_OPENCL_EXTN_QCOM
#define TVM_INFO_USE_OPENCL_EXTN_QCOM "NOT-FOUND"
#endif

#ifndef TVM_INFO_USE_OPENCL_GTEST
#define TVM_INFO_USE_OPENCL_GTEST "NOT-FOUND"
#endif
Expand Down Expand Up @@ -362,6 +366,7 @@ TVM_DLL Map<String, String> GetLibInfo() {
{"USE_NNPACK", TVM_INFO_USE_NNPACK},
{"USE_OPENCL", TVM_INFO_USE_OPENCL},
{"USE_OPENCL_ENABLE_HOST_PTR", TVM_INFO_USE_OPENCL_ENABLE_HOST_PTR},
{"USE_OPENCL_EXTN_QCOM", TVM_INFO_USE_OPENCL_EXTN_QCOM},
{"USE_OPENCL_GTEST", TVM_INFO_USE_OPENCL_GTEST},
{"USE_OPENMP", TVM_INFO_USE_OPENMP},
{"USE_PAPI", TVM_INFO_USE_PAPI},
Expand Down
50 changes: 50 additions & 0 deletions tests/cpp-runtime/opencl/aa_opencl_qcom_extn.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* 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.
*/

// Note:: This should be first tests to be executed.
// hence, crafted the filename accordingly

#include <gtest/gtest.h>
#include <tvm/runtime/container/optional.h>

#include "../src/runtime/opencl/opencl_common.h"

using namespace tvm::runtime;
using namespace tvm::runtime::cl;

#ifdef USE_OPENCL_EXTN_QCOM
#pragma message("Qualcomm OpenCL Extn GTests: enabled")
TEST(QCOMExtn, ContextPriorityHint) {
OpenCLWorkspace* workspace = OpenCLWorkspace::Global();
cl_context_properties properties[] = {CL_CONTEXT_PRIORITY_HINT_QCOM, CL_PRIORITY_HINT_LOW_QCOM,
0};
// Only allow one time
ASSERT_EQ(workspace->Init(properties), true);
// Subsequent calls will be failure
ASSERT_EQ(workspace->Init(properties), false);
}

TEST(QCOMExtn, ContextPerfHint) {
OpenCLWorkspace* workspace = OpenCLWorkspace::Global();
auto dev = DLDevice{kDLOpenCL, 0};
workspace->SetPerfHint(dev, CL_PERF_HINT_HIGH_QCOM);
}
#else
#pragma message("Qualcomm OpenCL Extn GTests: disabled")
#endif
2 changes: 2 additions & 0 deletions tests/scripts/task_build_adreno_bins.sh
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ echo set\(MACHINE_NAME aarch64-linux-gnu\) >> config.cmake

echo set\(USE_OPENCL_GTEST ON\) >> config.cmake

echo set\(USE_OPENCL_EXTN_QCOM ON\) >> config.cmake

cmake -DCMAKE_TOOLCHAIN_FILE="${ANDROID_NDK_HOME}/build/cmake/android.toolchain.cmake" \
-DANDROID_ABI=arm64-v8a \
-DANDROID_PLATFORM=android-28 \
Expand Down

0 comments on commit 37bca85

Please sign in to comment.