libopencl — OpenCL Runtime API

OpenCL 1.x Runtime API Translation Layer

Implements libOpenCL.so as a drop-in replacement for the NVIDIA OpenCL driver. OpenCL calls are translated into the same GPGPU-Sim simulator infrastructure used by CUDA β€” OpenCL source is compiled to PTX via nvopencl_wrapper, then loaded into the simulator's PTX parser for cycle-accurate execution.

2
Source Files
OpenCL
API Layer
30+
Functions
C++
Language

OpenCL 1.x PTX Compilation NDRange β†’ Grid

πŸ’‘ What is libopencl?

Analogy: If libcuda is the "customs checkpoint" for CUDA traffic, libopencl is the translator booth next door β€” it accepts OpenCL-speaking applications, translates their requests into the same internal language (PTX + kernel_info_t), and sends them through the same simulation pipeline. The translation includes compiling OpenCL C source to PTX and mapping OpenCL's NDRange work dimensions to CUDA-style grid/block dimensions.

Architecture

flowchart LR
  subgraph App["OpenCL Application"]
    A1["clCreateBuffer()"]
    A2["clBuildProgram()"]
    A3["clEnqueueNDRange()"]
  end
  subgraph Libopencl["libopencl / opencl_runtime_api.cc"]
    B1["_cl_context\nMemory management"]
    B2["_cl_program\nnvopencl_wrapper"]
    B3["_cl_kernel\nArgument binding"]
    B4["NDRange Mapper\nglobal→grid/block"]
  end
  subgraph Core["GPGPU-Sim Core"]
    C1["gpgpu_opencl_ptx_sim_main_perf()"]
    C2["gpgpu_sim::cycle()"]
  end
  A1 --> B1
  A2 --> B2
  A3 --> B3
  B3 --> B4
  B2 --> B3
  B1 --> C1
  B4 --> C1
  C1 --> C2

Data Flow β€” OpenCL Kernel Execution

flowchart TD
  S1["clCreateProgramWithSource()\nStore OpenCL C source"] --> S2["clBuildProgram()\nInvoke nvopencl_wrapper"]
  S2 --> S3["nvopencl_wrapper\nOpenCL C β†’ PTX compilation"]
  S3 --> S4["gpgpu_ptx_sim_load_ptx_from_string()\nBuild symbol_table"]
  S4 --> S5["clCreateKernel()\nLookup function_info* by name"]
  S5 --> S6["clSetKernelArg() Γ— N\nBind arguments by index"]
  S6 --> S7["clEnqueueNDRangeKernel()\nMap work dims β†’ grid/block"]
  S7 --> S8["Create kernel_info_t\ngridDim Γ— blockDim"]
  S8 --> S9["gpgpu_opencl_ptx_sim_main_perf()\nCycle-level simulation"]

OpenCL β†’ CUDA Concept Mapping

flowchart LR
  subgraph OpenCL["OpenCL Concepts"]
    OA["cl_platform_id"]
    OB["cl_device_id"]
    OC["cl_context"]
    OD["cl_command_queue"]
    OE["cl_mem"]
    OF["cl_program"]
    OG["cl_kernel"]
    OH["NDRange\nglobal Γ— local"]
  end
  subgraph CUDA["Simulator Internal"]
    CA["Singleton"]
    CB["_cuda_device_id"]
    CC["CUctx_st"]
    CD["CUstream_st"]
    CE["Device pointer"]
    CF["symbol_table"]
    CG["function_info*"]
    CH["gridDim Γ— blockDim"]
  end
  OA --> CA
  OB --> CB
  OC --> CC
  OD --> CD
  OE --> CE
  OF --> CF
  OG --> CG
  OH --> CH

🚢 Step-by-Step Narrated Walkthrough

Follow a single clEnqueueNDRangeKernel() call through the libopencl pipeline:

  1. Platform Discovery β€” clGetPlatformIDs() returns the singleton g_gpgpu_sim_platform_id. The application sees one GPGPU-Sim platform.
  2. Device Selection β€” clGetDeviceIDs() returns a _cl_device_id wrapping the simulated gpgpu_sim instance.
  3. Context Creation β€” clCreateContext() creates a _cl_context binding the device, initialising the memory map m_hostptr_to_cl_mem.
  4. Program Compilation β€” clCreateProgramWithSource() stores the OpenCL C source string. clBuildProgram() writes it to a temp file, invokes nvopencl_wrapper, reads back PTX, and calls gpgpu_ptx_sim_load_ptx_from_string().
  5. Kernel Creation β€” clCreateKernel(name) looks up the function_info* in pgm_info::m_kernels by kernel name.
  6. Argument Binding β€” Each clSetKernelArg(index, size, value) stores an arg_info in the kernel's argument map.
  7. Work Dimension Mapping β€” clEnqueueNDRangeKernel() computes GridDim = global_work_size / local_work_size for each of 1–3 dimensions.
  8. Kernel Launch β€” A kernel_info_t is created with the computed grid/block dims and enqueued via gpgpu_opencl_ptx_sim_main_perf().
  9. Simulation β€” The core gpgpu_sim::cycle() loop executes the kernel to completion.
  10. Synchronisation β€” clFinish() blocks until all enqueued operations complete on the command queue.

Key Classes & Structures

#Class / StructFileDescription
1_cl_platform_idopencl_runtime_api.ccSingleton platform with static m_uid=0. Global instance g_gpgpu_sim_platform_id.
2_cl_device_idopencl_runtime_api.ccDevice wrapping gpgpu_sim *m_gpgpu. Methods: next(), the_device().
3_cl_contextopencl_runtime_api.ccContext holding device ref and memory map m_hostptr_to_cl_mem. Methods: CreateBuffer(), lookup_mem().
4_cl_memopencl_runtime_api.ccMemory object: m_device_ptr, m_host_ptr, m_is_on_host. Supports USE/ALLOC/COPY host pointer modes.
5_cl_command_queueopencl_runtime_api.ccCommand queue: m_context, m_device. Warns if out-of-order property used.
6_cl_programopencl_runtime_api.ccProgram from source. m_pgm map of pgm_info per device. Methods: Build(), CreateKernel(), get_ptx().
7pgm_infoopencl_runtime_api.ccPer-device program metadata: m_source, m_asm (compiled PTX), m_symtab, m_kernels.
8_cl_kernelopencl_runtime_api.ccKernel object: m_kernel_name, m_kernel_impl, m_args. Methods: SetKernelArg(), bind_args().
9arg_infoopencl_runtime_api.ccPer-argument descriptor: index, size, and value pointer for kernel arguments.
10function_infoptx_ir.h (external)Decoded PTX kernel representation shared with libcuda.

Key API Functions

CategoryFunctionPurpose
PlatformclGetPlatformIDs()Returns 1 platform (GPGPU-Sim)
DeviceclGetDeviceIDs()Returns simulated GPU device
DeviceclGetDeviceInfo()80+ attributes from sim config
ContextclCreateContext()Creates _cl_context wrapping device
QueueclCreateCommandQueue()Creates _cl_command_queue
MemoryclCreateBuffer()Allocates on simulated GPU via gpu_malloc()
ProgramclCreateProgramWithSource()Stores OpenCL C source string
ProgramclBuildProgram()Compiles via nvopencl_wrapper β†’ PTX
KernelclCreateKernel()Extracts function_info* by kernel name
KernelclSetKernelArg()Sets argument by index
ExecuteclEnqueueNDRangeKernel()Maps NDRange β†’ grid/block, creates kernel_info_t, launches
TransferclEnqueueReadBuffer()Device β†’ host via memcpy_from_gpu()
TransferclEnqueueWriteBuffer()Host β†’ device via memcpy_to_gpu()
SyncclFinish()Synchronises command queue

Module Interactions

Interacts WithDirectionMechanismPurpose
OpenCL Application← inboundLD_PRELOAD / link-timeIntercepts all cl*() API calls
nvopencl_wrapper→ outboundProcess invocationCompiles OpenCL C source to PTX via NVIDIA compiler
cuda-sim (PTX parser)β†’ outboundgpgpu_ptx_sim_load_ptx_from_string()Loads compiled PTX into the functional simulator
gpgpu_sim core→ outboundgpgpu_opencl_ptx_sim_main_perf()Launches kernel for cycle-level execution
libcuda↔ shared infraSame simulator internalsBoth create kernel_info_t and share gpgpu_sim core

Configuration & Environment Variables

VariableTypeDescription
OPENCL_REMOTE_GPU_HOSTEnvHostname for remote OpenCL compilation (if local GPU unavailable)
NVOPENCL_LIBDIREnvPath to NVIDIA's OpenCL compiler library
LD_LIBRARY_PATHEnvMust include NVIDIA OpenCL driver libs
CUDA_INSTALL_PATHEnvRequired for nvopencl_wrapper compilation

Code Snippets

Work Dimension Mapping β€” NDRange to Grid/Block

// opencl_runtime_api.cc β€” clEnqueueNDRangeKernel core logic
// Map OpenCL work dimensions to CUDA grid/block dimensions
dim3 GridDim, BlockDim;

GridDim.x = global_work_size[0] / local_work_size[0];
GridDim.y = (work_dim >= 2) ? global_work_size[1] / local_work_size[1] : 1;
GridDim.z = (work_dim >= 3) ? global_work_size[2] / local_work_size[2] : 1;

BlockDim.x = local_work_size[0];
BlockDim.y = (work_dim >= 2) ? local_work_size[1] : 1;
BlockDim.z = (work_dim >= 3) ? local_work_size[2] : 1;

// Create kernel_info_t and launch
kernel_info_t *grid = new kernel_info_t(GridDim, BlockDim, entry);
gpgpu_opencl_ptx_sim_main_perf(grid);

Program Build β€” OpenCL Source to PTX

// _cl_program::Build() β€” simplified
cl_int _cl_program::Build(const char *options) {
  // 1. Write OpenCL source to temp file
  FILE *fp = fopen(src_filename, "w");
  fprintf(fp, "%s", m_pgm[device].m_source.c_str());
  fclose(fp);

  // 2. Invoke nvopencl_wrapper (NVIDIA's compiler)
  std::string cmd = "nvopencl_wrapper " + src_filename;
  if (getenv("OPENCL_REMOTE_GPU_HOST"))
    cmd = "ssh " + remote_host + " " + cmd;
  system(cmd.c_str());

  // 3. Read compiled PTX and load into simulator
  std::string ptx = read_file(ptx_filename);
  gpgpu_ptx_sim_load_ptx_from_string(ptx, source_num);
  return CL_SUCCESS;
}

Directory Map

Source tree for libopencl
libopencl/
β”œβ”€β”€ opencl_runtime_api.cc  ← 1,540 lines β€” implements 30+ cl*() API functions
β”‚                             Defines all _cl_* classes inline
β”œβ”€β”€ nvopencl_wrapper.cc    ← Wrapper for NVIDIA's OpenCL-to-PTX compiler
β”œβ”€β”€ Makefile               ← Builds libOpenCL.so
└── CMakeLists.txt         ← CMake build configuration

Glossary

TermDefinition
NDRangeN-Dimensional Range β€” OpenCL's equivalent of CUDA grid + block launch specification
Work GroupOpenCL equivalent of CUDA thread block (CTA) β€” threads that can synchronise via barriers
Work ItemOpenCL equivalent of a single CUDA thread
nvopencl_wrapperGPGPU-Sim script that invokes NVIDIA's OpenCL compiler to produce PTX from OpenCL C source
cl_memOpenCL memory object representing a buffer on the device (mapped to a simulated GPU address)
Command QueueOrdered sequence of OpenCL operations β€” analogous to a CUDA stream