mirror of https://github.com/alibaba/MNN.git
245 lines
8.8 KiB
C++
245 lines
8.8 KiB
C++
//
|
|
// OpenCLProgramBuildTest.cpp
|
|
// MNN
|
|
//
|
|
// Created by MNN on 2025/5/15.
|
|
// Copyright © 2018, Alibaba Group Holding Limited
|
|
//
|
|
|
|
#include <fstream>
|
|
#include <string>
|
|
#include <vector>
|
|
#include "CL/cl.h"
|
|
#ifdef _WIN32
|
|
#include <windows.h>
|
|
#include <libloaderapi.h>
|
|
#else
|
|
#include <dlfcn.h>
|
|
#endif
|
|
|
|
using clGetPlatformIDsFunc = cl_int (CL_API_CALL *)(cl_uint, cl_platform_id *, cl_uint *);
|
|
using clBuildProgramFunc = cl_int (CL_API_CALL *)(cl_program, cl_uint, const cl_device_id *, const char *, void (CL_CALLBACK *pfn_notify)(cl_program, void *), void *);
|
|
using clCreateProgramWithSourceFunc = cl_program (CL_API_CALL *)(cl_context, cl_uint, const char **, const size_t *, cl_int *);
|
|
using clGetProgramBuildInfoFunc = cl_int (CL_API_CALL *)(cl_program, cl_device_id, cl_program_build_info, size_t, void *, size_t *);
|
|
using clCreateContextFunc = cl_context (CL_API_CALL *)(const cl_context_properties *, cl_uint, const cl_device_id *,
|
|
void(CL_CALLBACK *)( // NOLINT(readability/casting)
|
|
const char *, const void *, size_t, void *),
|
|
void *, cl_int *);
|
|
using clGetDeviceIDsFunc = cl_int (CL_API_CALL *)(cl_platform_id, cl_device_type, cl_uint, cl_device_id *, cl_uint *);
|
|
using clGetDeviceInfoFunc = cl_int (CL_API_CALL *)(cl_device_id, cl_device_info, size_t, void *, size_t *);
|
|
using clReleaseProgramFunc = cl_int (CL_API_CALL *)(cl_program program);
|
|
using clReleaseContextFunc = cl_int (CL_API_CALL *)(cl_context);
|
|
using clReleaseDeviceFunc = cl_int (CL_API_CALL *)(cl_device_id);
|
|
|
|
|
|
class OpenCLProgramTest {
|
|
public:
|
|
OpenCLProgramTest(){
|
|
static const std::vector<std::string> gOpencl_library_paths = {
|
|
|
|
#if defined(__APPLE__) || defined(__MACOSX)
|
|
"libOpenCL.so", "/System/Library/Frameworks/OpenCL.framework/OpenCL"
|
|
#elif defined(__OHOS__)
|
|
"/vendor/lib64/chipsetsdk/libhvgr_v200.so",
|
|
"/vendor/lib64/chipsetsdk/libGLES_mali.so",
|
|
"/system/lib64/libGLES_mali.so",
|
|
"libGLES_mali.so",
|
|
"/vendor/lib64/chipsetsdk/libEGI_imp1.so",
|
|
#elif defined(__ANDROID__)
|
|
"libOpenCL.so",
|
|
"libGLES_mali.so",
|
|
"libmali.so",
|
|
"libOpenCL-pixel.so",
|
|
#if defined(__aarch64__)
|
|
// Qualcomm Adreno
|
|
"/system/vendor/lib64/libOpenCL.so",
|
|
"/system/lib64/libOpenCL.so",
|
|
// Mali
|
|
"/system/vendor/lib64/egl/libGLES_mali.so",
|
|
"/system/lib64/egl/libGLES_mali.so",
|
|
#else
|
|
// Qualcomm Adreno
|
|
"/system/vendor/lib/libOpenCL.so", "/system/lib/libOpenCL.so",
|
|
// Mali
|
|
"/system/vendor/lib/egl/libGLES_mali.so", "/system/lib/egl/libGLES_mali.so",
|
|
// other
|
|
"/system/vendor/lib/libPVROCL.so", "/data/data/org.pocl.libs/files/lib/libpocl.so"
|
|
#endif
|
|
#elif defined(__linux__)
|
|
"/usr/lib/libOpenCL.so",
|
|
"/usr/local/lib/libOpenCL.so",
|
|
"/usr/local/lib/libpocl.so",
|
|
"/usr/lib64/libOpenCL.so",
|
|
"/usr/lib32/libOpenCL.so",
|
|
"libOpenCL.so"
|
|
#elif defined(_WIN64)
|
|
"C:/Windows/System32/OpenCL.dll",
|
|
"C:/Windows/SysWOW64/OpenCL.dll"
|
|
#elif defined(_WIN32)
|
|
"C:/Windows/SysWOW64/OpenCL.dll",
|
|
"C:/Windows/System32/OpenCL.dll"
|
|
#endif
|
|
};
|
|
|
|
for (const auto &opencl_lib : gOpencl_library_paths) {
|
|
if (LoadLibraryFromPath(opencl_lib)) {
|
|
mIsSupportAvailable = true;
|
|
}
|
|
}
|
|
if(mIsSupportAvailable){
|
|
cl_int err;
|
|
err = clGetPlatformIDs(1, &platform, NULL);
|
|
if (err != CL_SUCCESS) {
|
|
printf("Failed to get platform ID err = %d\n", err);
|
|
return ;
|
|
}
|
|
err = clGetDeviceIDs(platform, CL_DEVICE_TYPE_GPU, 1, &device, NULL);
|
|
if (err != CL_SUCCESS) {
|
|
printf("Failed to get device ID err = %d\n", err);
|
|
return;
|
|
}
|
|
|
|
context = clCreateContext(NULL, 1, &device, NULL, NULL, &err);
|
|
if (!context || err != CL_SUCCESS) {
|
|
printf("Failed to create context err = %d\n", err);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
bool LoadLibraryFromPath(const std::string &library_path){
|
|
#if defined(_WIN32)
|
|
handle_ = LoadLibraryA(library_path.c_str());
|
|
if (handle_ == nullptr) {
|
|
return false;
|
|
}
|
|
#define MNN_LOAD_FUNCTION_PTR(func_name) func_name = reinterpret_cast<func_name##Func>(GetProcAddress(static_cast<HMODULE>(handle_), #func_name));
|
|
#else
|
|
handle_ = dlopen(library_path.c_str(), RTLD_NOW | RTLD_LOCAL);
|
|
if (handle_ == nullptr) {
|
|
return false;
|
|
}
|
|
#define MNN_LOAD_FUNCTION_PTR(func_name) func_name = reinterpret_cast<func_name##Func>(dlsym(handle_, #func_name));
|
|
#endif
|
|
MNN_LOAD_FUNCTION_PTR(clGetPlatformIDs);
|
|
MNN_LOAD_FUNCTION_PTR(clBuildProgram);
|
|
MNN_LOAD_FUNCTION_PTR(clCreateProgramWithSource);
|
|
MNN_LOAD_FUNCTION_PTR(clGetProgramBuildInfo);
|
|
MNN_LOAD_FUNCTION_PTR(clCreateContext);
|
|
MNN_LOAD_FUNCTION_PTR(clGetDeviceIDs);
|
|
MNN_LOAD_FUNCTION_PTR(clGetDeviceInfo);
|
|
MNN_LOAD_FUNCTION_PTR(clReleaseProgram);
|
|
MNN_LOAD_FUNCTION_PTR(clReleaseContext);
|
|
MNN_LOAD_FUNCTION_PTR(clReleaseDevice);
|
|
|
|
return true;
|
|
}
|
|
bool TestProgram(const std::vector<std::string> options){
|
|
cl_int err;
|
|
FILE* file = fopen("kernel.cl", "r");
|
|
if (!file) {
|
|
printf("Failed to open kernel file: kernel.cl\n");
|
|
return false;
|
|
}
|
|
|
|
fseek(file, 0, SEEK_END);
|
|
size_t fileSize = ftell(file);
|
|
rewind(file);
|
|
|
|
char* source = (char*)malloc(fileSize + 1);
|
|
if (!source) {
|
|
fclose(file);
|
|
printf("Memory allocation failed for kernel source\n");
|
|
return false;
|
|
}
|
|
|
|
fread(source, sizeof(char), fileSize, file);
|
|
source[fileSize] = '\0';
|
|
fclose(file);
|
|
|
|
// test program
|
|
const char *code = source;
|
|
cl_program program = clCreateProgramWithSource(context, 1, &code, &fileSize, &err);
|
|
if (!program || err != CL_SUCCESS) {
|
|
printf("Failed to create program from source\n");
|
|
return false;
|
|
}
|
|
for(int i = 0; i < options.size(); ++i){
|
|
err = clBuildProgram(program, 1, &device, options[i].c_str(), NULL, NULL);
|
|
if (err != CL_SUCCESS) {
|
|
size_t logSize;
|
|
clGetProgramBuildInfo(program, device, CL_PROGRAM_BUILD_LOG, 0, NULL, &logSize);
|
|
char *buildLog = (char*)malloc(logSize);
|
|
clGetProgramBuildInfo(program, device, CL_PROGRAM_BUILD_LOG, logSize, buildLog, NULL);
|
|
printf("Program build log: ");
|
|
for (int i = 0; i < logSize; i++) {
|
|
printf("%c", buildLog[i]);
|
|
}
|
|
clReleaseProgram(program);
|
|
free(buildLog);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
clReleaseProgram(program);
|
|
free(source);
|
|
return true;
|
|
}
|
|
bool mIsSupportAvailable = false;
|
|
~OpenCLProgramTest(){
|
|
if(mIsSupportAvailable){
|
|
clReleaseDevice(device);
|
|
clReleaseContext(context);
|
|
}
|
|
if (handle_ != nullptr) {
|
|
#if defined(_WIN32)
|
|
FreeLibrary(static_cast<HMODULE>(handle_));
|
|
#else
|
|
dlclose(handle_);
|
|
#endif
|
|
}
|
|
}
|
|
private:
|
|
void *handle_ = nullptr;
|
|
clGetPlatformIDsFunc clGetPlatformIDs;
|
|
clBuildProgramFunc clBuildProgram;
|
|
clCreateProgramWithSourceFunc clCreateProgramWithSource;
|
|
clGetProgramBuildInfoFunc clGetProgramBuildInfo;
|
|
clCreateContextFunc clCreateContext;
|
|
clGetDeviceIDsFunc clGetDeviceIDs;
|
|
clGetDeviceInfoFunc clGetDeviceInfo;
|
|
clReleaseProgramFunc clReleaseProgram;
|
|
clReleaseContextFunc clReleaseContext;
|
|
clReleaseDeviceFunc clReleaseDevice;
|
|
cl_platform_id platform;
|
|
cl_device_id device;
|
|
cl_context context;
|
|
};
|
|
|
|
int main(int argc, char *argv[]) {
|
|
std::string filename;
|
|
if(argc > 1){
|
|
filename = argv[1];
|
|
}
|
|
std::vector<std::string> options;
|
|
std::fstream file("option.txt");
|
|
if(file.is_open()){
|
|
std::string line;
|
|
while (getline(file, line)) { // 按行读取文件内容并输出
|
|
options.push_back(line);
|
|
}
|
|
file.close();
|
|
}
|
|
printf("test filename is %s\n", filename.c_str());
|
|
OpenCLProgramTest BuildTest;
|
|
if(BuildTest.mIsSupportAvailable){
|
|
if(BuildTest.TestProgram(options)){
|
|
return 0;
|
|
}
|
|
}else{
|
|
printf("OpenCL init fail\n");
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
|