| #define __HIP_PLATFORM_AMD__ |
| |
| |
| #include <hip/hip_runtime.h> |
| #include <hip/hip_deprecated.h> |
| |
| #define PY_SSIZE_T_CLEAN |
| #include <Python.h> |
| #include <dlfcn.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
|
|
| |
| |
| static const char *hipLibSearchPaths[] = {"/*py_libhip_search_path*/"}; |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| #define HIP_SYMBOL_LIST(FOR_EACH_ERR_FN, FOR_EACH_STR_FN) \ |
| FOR_EACH_STR_FN(hipGetErrorString, hipError_t hipError) \ |
| FOR_EACH_ERR_FN(hipGetDeviceProperties, hipDeviceProp_tR0000 *prop, \ |
| int deviceId) \ |
| FOR_EACH_ERR_FN(hipModuleLoadDataEx, hipModule_t *module, const void *image, \ |
| unsigned int numOptions, hipJitOption *options, \ |
| void **optionValues) \ |
| FOR_EACH_ERR_FN(hipModuleGetFunction, hipFunction_t *function, \ |
| hipModule_t module, const char *kname) \ |
| FOR_EACH_ERR_FN(hipFuncGetAttribute, int *, hipFunction_attribute attr, \ |
| hipFunction_t function) |
|
|
| |
| struct HIPSymbolTable { |
| #define DEFINE_EACH_ERR_FIELD(hipSymbolName, ...) \ |
| hipError_t (*hipSymbolName)(__VA_ARGS__); |
| #define DEFINE_EACH_STR_FIELD(hipSymbolName, ...) \ |
| const char *(*hipSymbolName)(__VA_ARGS__); |
|
|
| HIP_SYMBOL_LIST(DEFINE_EACH_ERR_FIELD, DEFINE_EACH_STR_FIELD) |
| }; |
|
|
| static struct HIPSymbolTable hipSymbolTable; |
|
|
| bool initSymbolTable() { |
| |
| void *lib = dlopen("libamdhip64.so", RTLD_NOLOAD); |
| if (lib) { |
| |
| } |
|
|
| |
| |
| if (!lib) { |
| int n = sizeof(hipLibSearchPaths) / sizeof(hipLibSearchPaths[0]); |
| for (int i = 0; i < n; ++i) { |
| void *handle = dlopen(hipLibSearchPaths[i], RTLD_LAZY | RTLD_LOCAL); |
| if (handle) { |
| lib = handle; |
| |
| } |
| } |
| } |
| if (!lib) { |
| PyErr_SetString(PyExc_RuntimeError, "cannot open libamdhip64.so"); |
| return false; |
| } |
|
|
| |
| dlerror(); |
| const char *error = NULL; |
| #define QUERY_EACH_FN(hipSymbolName, ...) \ |
| *(void **)&hipSymbolTable.hipSymbolName = dlsym(lib, #hipSymbolName); \ |
| error = dlerror(); \ |
| if (error) { \ |
| PyErr_SetString(PyExc_RuntimeError, \ |
| "cannot query " #hipSymbolName " from libamdhip64.so"); \ |
| dlclose(lib); \ |
| return false; \ |
| } |
|
|
| HIP_SYMBOL_LIST(QUERY_EACH_FN, QUERY_EACH_FN) |
|
|
| return true; |
| } |
|
|
| static inline void gpuAssert(hipError_t code, const char *file, int line) { |
| { |
| if (code != HIP_SUCCESS) { |
| { |
| const char *prefix = "Triton Error [HIP]: "; |
| const char *str = hipSymbolTable.hipGetErrorString(code); |
| char err[1024] = {0}; |
| snprintf(err, 1024, "%s Code: %d, Messsage: %s", prefix, code, str); |
| PyGILState_STATE gil_state; |
| gil_state = PyGILState_Ensure(); |
| PyErr_SetString(PyExc_RuntimeError, err); |
| PyGILState_Release(gil_state); |
| } |
| } |
| } |
| } |
|
|
| #define HIP_CHECK(ans) \ |
| { \ |
| gpuAssert((ans), __FILE__, __LINE__); \ |
| if (PyErr_Occurred()) \ |
| return NULL; \ |
| } |
|
|
| static PyObject *getDeviceProperties(PyObject *self, PyObject *args) { |
| int device_id; |
| if (!PyArg_ParseTuple(args, "i", &device_id)) |
| return NULL; |
|
|
| hipDeviceProp_tR0000 props; |
| HIP_CHECK(hipSymbolTable.hipGetDeviceProperties(&props, device_id)); |
|
|
| |
| return Py_BuildValue( |
| "{s:i, s:i, s:i, s:i, s:i, s:i, s:s, s:i}", "max_shared_mem", |
| props.sharedMemPerBlock, "max_num_regs", props.regsPerBlock, |
| "multiprocessor_count", props.multiProcessorCount, "sm_clock_rate", |
| props.clockRate, "mem_clock_rate", props.memoryClockRate, "mem_bus_width", |
| props.memoryBusWidth, "arch", props.gcnArchName, "warpSize", |
| props.warpSize); |
| } |
|
|
| static PyObject *loadBinary(PyObject *self, PyObject *args) { |
| const char *name; |
| const char *data; |
| Py_ssize_t data_size; |
| int shared; |
| int device; |
| if (!PyArg_ParseTuple(args, "ss#ii", &name, &data, &data_size, &shared, |
| &device)) { |
| return NULL; |
| } |
|
|
| |
| hipJitOption opt[] = {hipJitOptionErrorLogBufferSizeBytes, |
| hipJitOptionErrorLogBuffer, |
| hipJitOptionInfoLogBufferSizeBytes, |
| hipJitOptionInfoLogBuffer, hipJitOptionLogVerbose}; |
| const unsigned int errbufsize = 8192; |
| const unsigned int logbufsize = 8192; |
| char _err[errbufsize]; |
| char _log[logbufsize]; |
| void *optval[] = {(void *)(uintptr_t)errbufsize, (void *)_err, |
| (void *)(uintptr_t)logbufsize, (void *)_log, (void *)1}; |
|
|
| |
| hipModule_t mod; |
| hipFunction_t fun; |
| HIP_CHECK(hipSymbolTable.hipModuleLoadDataEx(&mod, data, 5, opt, optval)) |
| HIP_CHECK(hipSymbolTable.hipModuleGetFunction(&fun, mod, name)); |
|
|
| |
| int n_regs = 0; |
| int n_spills = 0; |
| hipSymbolTable.hipFuncGetAttribute(&n_regs, HIP_FUNC_ATTRIBUTE_NUM_REGS, fun); |
| hipSymbolTable.hipFuncGetAttribute(&n_spills, |
| HIP_FUNC_ATTRIBUTE_LOCAL_SIZE_BYTES, fun); |
| n_spills /= 4; |
| if (PyErr_Occurred()) { |
| return NULL; |
| } |
| return Py_BuildValue("(KKii)", (uint64_t)mod, (uint64_t)fun, n_regs, |
| n_spills); |
| } |
|
|
| static PyMethodDef ModuleMethods[] = { |
| {"load_binary", loadBinary, METH_VARARGS, |
| "Load provided hsaco into HIP driver"}, |
| {"get_device_properties", getDeviceProperties, METH_VARARGS, |
| "Get the properties for a given device"}, |
| {NULL, NULL, 0, NULL} |
| }; |
|
|
| static struct PyModuleDef ModuleDef = {PyModuleDef_HEAD_INIT, "hip_utils", |
| NULL, |
| -1, |
| ModuleMethods}; |
|
|
| PyMODINIT_FUNC PyInit_hip_utils(void) { |
| if (!initSymbolTable()) { |
| return NULL; |
| } |
|
|
| PyObject *m = PyModule_Create(&ModuleDef); |
| if (m == NULL) { |
| return NULL; |
| } |
| PyModule_AddFunctions(m, ModuleMethods); |
|
|
| return m; |
| } |
|
|