Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions include/infinicore.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ typedef enum {
INFINI_DEVICE_KUNLUN = 7,
INFINI_DEVICE_HYGON = 8,
INFINI_DEVICE_QY = 9,
INFINI_DEVICE_OPENCL = 10,
INFINI_DEVICE_TYPE_COUNT
} infiniDevice_t;

Expand Down
7 changes: 7 additions & 0 deletions src/infinirt-test/main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ void printUsage() {
<< " qy" << std::endl
<< " kunlun" << std::endl
<< " hygon" << std::endl
<< " opencl" << std::endl
<< std::endl;
exit(EXIT_FAILURE);
}
Expand Down Expand Up @@ -55,6 +56,7 @@ ParsedArgs parseArgs(int argc, char *argv[]) {
else PARSE_DEVICE("--qy", INFINI_DEVICE_QY)
else PARSE_DEVICE("--kunlun", INFINI_DEVICE_KUNLUN)
else PARSE_DEVICE("--hygon", INFINI_DEVICE_HYGON)
else PARSE_DEVICE("--opencl", INFINI_DEVICE_OPENCL)
else {
printUsage();
}
Expand All @@ -73,6 +75,11 @@ int main(int argc, char *argv[]) {
std::cout << "Testing Device: " << args.device_type << std::endl;
infiniDevice_t device = args.device_type;

// 初始化
if (infinirtInit() != INFINI_STATUS_SUCCESS) {
std::cerr << "Failed to init device" << std::endl;
}

// 获取设备总数
std::vector<int> deviceCounts(INFINI_DEVICE_TYPE_COUNT, 0);
if (infinirtGetAllDeviceCount(deviceCounts.data()) != INFINI_STATUS_SUCCESS) {
Expand Down
8 changes: 7 additions & 1 deletion src/infinirt/infinirt.cc
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,16 @@
#include "kunlun/infinirt_kunlun.h"
#include "metax/infinirt_metax.h"
#include "moore/infinirt_moore.h"
#include "opencl/infinirt_opencl.h"

thread_local infiniDevice_t CURRENT_DEVICE_TYPE = INFINI_DEVICE_CPU;
thread_local int CURRENT_DEVICE_ID = 0;

__C infiniStatus_t infinirtInit() {
#ifdef ENABLE_ASCEND_API
#if defined(ENABLE_ASCEND_API)
CHECK_STATUS(infinirt::ascend::init());
#elif defined(ENABLE_OPENCL_API)
CHECK_STATUS(infinirt::opencl::init());
#endif
return INFINI_STATUS_SUCCESS;
}
Expand Down Expand Up @@ -79,6 +82,9 @@ __C infiniStatus_t infinirtGetDevice(infiniDevice_t *device_ptr, int *device_id_
case INFINI_DEVICE_HYGON: \
_status = infinirt::hygon::API PARAMS; \
break; \
case INFINI_DEVICE_OPENCL: \
_status = infinirt::opencl::API PARAMS; \
break; \
default: \
_status = INFINI_STATUS_DEVICE_TYPE_NOT_SUPPORTED; \
} \
Expand Down
299 changes: 299 additions & 0 deletions src/infinirt/opencl/infinirt_opencl.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,299 @@
#include "infinirt_opencl.h"
#include "../../utils.h"
#include <CL/cl.h>
#include <mutex>
#include <vector>

#define CHECK_CLRT(RT_API) CHECK_INTERNAL(RT_API, CL_SUCCESS)

static std::mutex init_mutex;
static cl_platform_id platform = nullptr;
static cl_context context = nullptr;
static std::vector<cl_device_id> devices;
static std::vector<std::vector<cl_command_queue>> queues;
static cl_uint device_count = 0;
static bool initialized = false;
thread_local int CUR_DEV_ID = 0;
struct InfinirtEventStruct {
cl_event ev = nullptr;
bool bound = false;
};

namespace infinirt::opencl {
static void cleanupResources() {
if (!queues.empty()) {
for (auto &qvec : queues) {
for (auto q : qvec) {
if (q) {
clReleaseCommandQueue(q);
}
}
qvec.clear();
}
queues.clear();
}
if (context) {
clReleaseContext(context);
context = nullptr;
}
devices.clear();
device_count = 0;
platform = nullptr;
initialized = false;
}
infiniStatus_t init() {
std::lock_guard<std::mutex> lk(init_mutex);
if (initialized) {
return INFINI_STATUS_SUCCESS;
}
cl_int err = CL_SUCCESS;
cl_uint num_platforms = 0;
err = clGetPlatformIDs(1, nullptr, &num_platforms);
if (err != CL_SUCCESS) {
cleanupResources();
return INFINI_STATUS_DEVICE_NOT_INITIALIZED;
}
if (num_platforms == 0) {
return INFINI_STATUS_DEVICE_NOT_FOUND;
}
err = clGetPlatformIDs(1, &platform, nullptr);
if (err != CL_SUCCESS) {
cleanupResources();
return INFINI_STATUS_DEVICE_NOT_INITIALIZED;
}
err = clGetDeviceIDs(platform, CL_DEVICE_TYPE_GPU, 0, nullptr, &device_count);
if (err != CL_SUCCESS) {
cleanupResources();
return INFINI_STATUS_DEVICE_NOT_INITIALIZED;
}
if (device_count == 0) {
return INFINI_STATUS_DEVICE_NOT_FOUND;
}
devices.resize(static_cast<size_t>(device_count));
err = clGetDeviceIDs(platform, CL_DEVICE_TYPE_GPU, device_count, devices.data(), nullptr);
if (err != CL_SUCCESS) {
cleanupResources();
return INFINI_STATUS_DEVICE_NOT_INITIALIZED;
}
context = clCreateContext(nullptr, device_count, devices.data(), nullptr, nullptr, &err);
if (err != CL_SUCCESS) {
cleanupResources();
return INFINI_STATUS_DEVICE_NOT_INITIALIZED;
}

queues.resize(static_cast<size_t>(device_count));
for (cl_uint i = 0; i < device_count; ++i) {
cl_command_queue q = clCreateCommandQueueWithProperties(context, devices[i], nullptr, &err);
if (err != CL_SUCCESS) {
// 清理已创建的队列和 context
cleanupResources();
return INFINI_STATUS_DEVICE_NOT_INITIALIZED;
}
queues[i].push_back(q); // 初始队列作为默认队列在 index 0
}
initialized = true;
return INFINI_STATUS_SUCCESS;
}

infiniStatus_t getDeviceCount(int *count) {
if (!count) {
return INFINI_STATUS_BAD_PARAM;
}
std::lock_guard<std::mutex> lk(init_mutex);
if (!initialized) {
return INFINI_STATUS_DEVICE_NOT_INITIALIZED;
}
*count = static_cast<int>(device_count);
return INFINI_STATUS_SUCCESS;
}

infiniStatus_t setDevice(int device_id) {
std::lock_guard<std::mutex> lk(init_mutex);
if (!initialized) {
return INFINI_STATUS_DEVICE_NOT_INITIALIZED;
}
if (device_id < 0 || device_id >= static_cast<int>(device_count)) {
return INFINI_STATUS_DEVICE_NOT_FOUND;
}
CUR_DEV_ID = device_id;
return INFINI_STATUS_SUCCESS;
}

infiniStatus_t deviceSynchronize() {
for (auto &q : queues[CUR_DEV_ID]) {
if (q) {
CHECK_CLRT(clFinish(q));
}
}
return INFINI_STATUS_SUCCESS;
}

infiniStatus_t streamCreate(infinirtStream_t *stream_ptr) {
cl_int err;
cl_command_queue queue = clCreateCommandQueueWithProperties(context, devices[CUR_DEV_ID], nullptr, &err);
CHECK_CLRT(err);
{
std::lock_guard<std::mutex> lk(init_mutex);
queues[CUR_DEV_ID].push_back(queue);
}
*stream_ptr = queue;
return INFINI_STATUS_SUCCESS;
}

infiniStatus_t streamDestroy(infinirtStream_t stream) {
{
std::lock_guard<std::mutex> lk(init_mutex);
auto &qvec = queues[CUR_DEV_ID];
auto it = std::find(qvec.begin(), qvec.end(), (cl_command_queue)stream);
if (it != qvec.end()) {
qvec.erase(it);
}
}
CHECK_CLRT(clReleaseCommandQueue((cl_command_queue)stream));
return INFINI_STATUS_SUCCESS;
}

infiniStatus_t streamSynchronize(infinirtStream_t stream) {
CHECK_CLRT(clFinish((cl_command_queue)stream));
return INFINI_STATUS_SUCCESS;
}

infiniStatus_t streamWaitEvent(infinirtStream_t stream, infinirtEvent_t event) {
InfinirtEventStruct *evs = static_cast<InfinirtEventStruct *>(event);
CHECK_CLRT(clWaitForEvents(1, &evs->ev));
return INFINI_STATUS_SUCCESS;
}

infiniStatus_t eventCreate(infinirtEvent_t *event_ptr) {
InfinirtEventStruct *event = new InfinirtEventStruct();
*event_ptr = static_cast<infinirtEvent_t>(event);
return INFINI_STATUS_SUCCESS;
}

infiniStatus_t eventCreateWithFlags(infinirtEvent_t *event_ptr, uint32_t flags) {
return INFINI_STATUS_NOT_IMPLEMENTED;
}

infiniStatus_t eventRecord(infinirtEvent_t event, infinirtStream_t stream) {
InfinirtEventStruct *evs = static_cast<InfinirtEventStruct *>(event);
CHECK_CLRT(clEnqueueMarkerWithWaitList((cl_command_queue)stream, 0, nullptr, &evs->ev));
evs->bound = true;
return INFINI_STATUS_SUCCESS;
}

infiniStatus_t eventQuery(infinirtEvent_t event, infinirtEventStatus_t *status_ptr) {
InfinirtEventStruct *evs = static_cast<InfinirtEventStruct *>(event);
if (!evs->ev) {
return INFINI_STATUS_INTERNAL_ERROR;
}
cl_int status;
CHECK_CLRT(clGetEventInfo(evs->ev, CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof(cl_int), &status, nullptr));
if (status == CL_COMPLETE) {
*status_ptr = INFINIRT_EVENT_COMPLETE;
} else {
*status_ptr = INFINIRT_EVENT_NOT_READY;
}
return INFINI_STATUS_SUCCESS;
}

infiniStatus_t eventSynchronize(infinirtEvent_t event) {
InfinirtEventStruct *evs = static_cast<InfinirtEventStruct *>(event);
if (!evs->ev) {
return INFINI_STATUS_INTERNAL_ERROR;
}
CHECK_CLRT(clWaitForEvents(1, &evs->ev));
return INFINI_STATUS_SUCCESS;
}

infiniStatus_t eventDestroy(infinirtEvent_t event) {
InfinirtEventStruct *evs = static_cast<InfinirtEventStruct *>(event);
if (!evs->ev) {
return INFINI_STATUS_INTERNAL_ERROR;
}
CHECK_CLRT(clReleaseEvent(evs->ev));
evs->ev = nullptr;
delete evs;
return INFINI_STATUS_SUCCESS;
}

infiniStatus_t eventElapsedTime(float *ms_ptr, infinirtEvent_t start, infinirtEvent_t end) {
return INFINI_STATUS_NOT_IMPLEMENTED;
}

infiniStatus_t mallocDevice(void **p_ptr, size_t size) {
void *p = clSVMAlloc(context, CL_MEM_READ_WRITE, size, 0);
if (!p) {
return INFINI_STATUS_NULL_POINTER;
}
*p_ptr = p;
return INFINI_STATUS_SUCCESS;
}

infiniStatus_t mallocHost(void **p_ptr, size_t size) {
void *p = clSVMAlloc(context, CL_MEM_READ_WRITE, size, 0);
if (!p) {
return INFINI_STATUS_NULL_POINTER;
}
*p_ptr = p;
return INFINI_STATUS_SUCCESS;
}

infiniStatus_t freeDevice(void *ptr) {
clSVMFree(context, ptr);
return INFINI_STATUS_SUCCESS;
}

infiniStatus_t freeHost(void *ptr) {
clSVMFree(context, ptr);
return INFINI_STATUS_SUCCESS;
}

infiniStatus_t memcpy(void *dst, const void *src, size_t size, infinirtMemcpyKind_t kind) {
cl_command_queue default_queue = queues[CUR_DEV_ID][0];
CHECK_CLRT(clEnqueueSVMMemcpy(default_queue, CL_TRUE, dst, src, size, 0, nullptr, nullptr));
return INFINI_STATUS_SUCCESS;
}

infiniStatus_t memcpyAsync(void *dst, const void *src, size_t size, infinirtMemcpyKind_t kind, infinirtStream_t stream) {
CHECK_CLRT(clEnqueueSVMMemcpy((cl_command_queue)stream, CL_FALSE, dst, src, size, 0, nullptr, nullptr));
return INFINI_STATUS_SUCCESS;
}
infiniStatus_t mallocAsync(void **p_ptr, size_t size, infinirtStream_t stream) {
return INFINI_STATUS_INTERNAL_ERROR;
}

infiniStatus_t freeAsync(void *ptr, infinirtStream_t stream) {
return INFINI_STATUS_INTERNAL_ERROR;
}
infiniStatus_t getOpenclDevice(infinirtOpenclDevice_t *cl_device) {
if (cl_device == nullptr) {
return INFINI_STATUS_NULL_POINTER;
}
*cl_device = static_cast<infinirtOpenclDevice_t>(devices[CUR_DEV_ID]);
return INFINI_STATUS_SUCCESS;
}
infiniStatus_t getOpenclContext(infinirtOpenclContext_t *cl_context) {
if (cl_context == nullptr) {
return INFINI_STATUS_NULL_POINTER;
}
*cl_context = static_cast<infinirtOpenclContext_t>(context);
return INFINI_STATUS_SUCCESS;
}
infiniStatus_t getOpenclStream(infinirtOpenclStream_t *cl_queue) {
if (cl_queue == nullptr) {
return INFINI_STATUS_NULL_POINTER;
}
*cl_queue = static_cast<infinirtOpenclStream_t>(queues[CUR_DEV_ID][0]);
return INFINI_STATUS_SUCCESS;
}
} // namespace infinirt::opencl

__C infiniStatus_t infinirtGetOpenclDevice(infinirtOpenclDevice_t *cl_device) {
return infinirt::opencl::getOpenclDevice(cl_device);
}
__C infiniStatus_t infinirtGetOpenclContext(infinirtOpenclContext_t *cl_context) {
return infinirt::opencl::getOpenclContext(cl_context);
}
__C infiniStatus_t infinirtGetOpenclStream(infinirtOpenclStream_t *cl_queue) {
return infinirt::opencl::getOpenclStream(cl_queue);
}
24 changes: 24 additions & 0 deletions src/infinirt/opencl/infinirt_opencl.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#ifndef __INFINIRT_OPENCL_H__
#define __INFINIRT_OPENCL_H__
#include "../infinirt_impl.h"

typedef void *infinirtOpenclDevice_t;
typedef void *infinirtOpenclContext_t;
typedef void *infinirtOpenclStream_t;

__C __export infiniStatus_t infinirtGetOpenclDevice(infinirtOpenclDevice_t *cl_device);
__C __export infiniStatus_t infinirtGetOpenclContext(infinirtOpenclContext_t *cl_context);
__C __export infiniStatus_t infinirtGetOpenclStream(infinirtOpenclStream_t *cl_command_queue);

#ifdef __cplusplus
namespace infinirt::opencl {
#ifdef ENABLE_OPENCL_API
infiniStatus_t init();
INFINIRT_DEVICE_API_IMPL
#else
INFINIRT_DEVICE_API_NOOP
#endif
} // namespace infinirt::opencl
#endif // __cplusplus

#endif // __INFINIRT_OPENCL_H__
Loading