OpenCL on Ubuntu: Getting the ICD Loader and Vendor Runtime to Agree

Setting up OpenCL on Ubuntu is not one apt-get command. The ICD loader, library, and vendor runtime must agree — here is how to verify the stack.

OpenCL on Ubuntu: Getting the ICD Loader and Vendor Runtime to Agree
Written by TechnoLynx Published on 11 Jul 2026

You run one apt-get command, clinfo prints something, and you assume OpenCL is ready. Then your first benchmark reports a speedup that looks wrong — because the runtime quietly enumerated your CPU, not the GPU you meant to target. Installing OpenCL on Ubuntu is not a single package install. It is provisioning three separate components that must agree, and then proving they agree before any real work begins.

That verification step is where most “working” OpenCL installs actually fail. The stack looks alive, clinfo returns exit code zero, kernels compile and run — and every performance number you collect on top of that is measured against the wrong device. For a GPU-acceleration effort, that is not a minor annoyance. It is a silently invalidated baseline that stalls the whole port.

What does “ubuntu install opencl” actually mean in practice?

The phrase implies a single act. In reality you are assembling a chain of three components, each maintained by a different party, each with its own failure mode:

  • The OpenCL library — the ABI your application links against. On Ubuntu this is usually ocl-icd-opencl-dev (headers plus the loader stub) and libOpenCL.so. It contains no device logic at all.
  • The ICD loader — the Installable Client Driver mechanism. libOpenCL.so is a dispatcher: at runtime it reads /etc/OpenCL/vendors/*.icd, each of which names a vendor’s real driver library. The loader forwards your API calls to whichever vendor runtime the ICD file points at.
  • The vendor compute runtime — the actual driver that talks to silicon. NVIDIA ships it inside the proprietary driver, AMD ships ROCm’s rocm-opencl-runtime, Intel ships the intel-opencl-icd (Compute Runtime / NEO). This is the only layer that knows how to run a kernel on the GPU.

The naive install grabs the library, sees libOpenCL.so resolve, and stops. But libOpenCL.so will happily load with zero GPU vendor ICDs present, or with only a CPU-backed ICD registered. It reports success because the loader itself is fine. The device it dispatches to is a separate question entirely — and it is the question that determines whether your compute runs on the GPU. This layered dispatch model is the same one covered in our walkthrough of how OpenCL works for ML inference on Linux; the setup problem is that dispatch model failing quietly.

Why the three layers must agree

A common failure is version skew between the loader and the vendor runtime. You install a recent intel-opencl-icd but leave an old ocl-icd-libopencl1 in place, or you install the NVIDIA driver’s OpenCL runtime while a leftover Mesa rusticl ICD advertises a competing platform. clinfo then lists two platforms — and your application, which probably takes the first platform and first device it finds, binds to whichever one enumerated first. That is often the CPU or a software rasteriser.

The evidence class here matters. This is an observed pattern across the GPU-porting work we do, not a benchmarked failure rate: the single most frequent reason a “GPU” OpenCL benchmark disappoints is that it never ran on the GPU. The kernel compiled, the queue executed, the wall-clock time came back — all on a CPU ICD that the loader was perfectly entitled to select.

The three layers agree when: the loader version supports the ICD format the vendor runtime writes; exactly one ICD points at the GPU vendor you intend to use; and the vendor runtime’s kernel driver (the kernel module, nvidia, amdgpu, or i915/xe) is loaded and matches the userspace runtime version. Break any link and you get either a hard error (better) or a silent CPU fallback (worse).

How do I verify with clinfo that OpenCL is running on my GPU?

clinfo is the arbiter. Do not read its exit code — read its device list. A correct install shows your target GPU as a CL_DEVICE_TYPE_GPU device under the vendor platform you expect.

Verification checklist

Run each step and confirm the stated condition before you trust any benchmark:

  1. Install clinfosudo apt-get install clinfo. It has no vendor dependencies; it only queries whatever ICDs are registered.
  2. Count platformsclinfo -l. You want exactly the vendor platforms you intend. Two GPU platforms or an unexpected “Portable Computing Language” / pocl / Mesa entry means a stray ICD is registered.
  3. Confirm device type — in full clinfo output, find your GPU and check Device Type reads GPU, not CPU. A CPU-only listing is the fallback trap.
  4. Confirm the device name — the Device Name field must name your actual card (e.g. NVIDIA GeForce RTX 4090, AMD Radeon, Intel Arc), not a generic CPU string.
  5. Inspect registered ICDsls /etc/OpenCL/vendors/ and cat each .icd. Each file contains one line: the path to a vendor .so. Remove any that point at a runtime you did not intend.
  6. Confirm the kernel driver is loadedlsmod | grep -E 'nvidia|amdgpu|i915|xe'. A userspace runtime with no matching kernel module cannot reach the GPU.

If step 3 or 4 disagrees with your intent, the install is not done — regardless of what any package manager reported. This is the same integrity check that underpins a proper GPU workload audit: you cannot decide whether a workload is GPU-parallelisable until you can prove the workload is actually reaching the GPU.

Vendor-specific steps on Ubuntu

The library and loader are vendor-neutral; the runtime is not. The table below summarises the runtime package and the kernel-module dependency per vendor. Treat it as a starting map, not a substitute for the vendor’s current documentation.

Vendor OpenCL runtime source Kernel module clinfo platform string (typical)
NVIDIA Proprietary driver (nvidia-driver-XXX), which bundles the OpenCL ICD nvidia NVIDIA CUDA
AMD ROCm rocm-opencl-runtime (or Mesa rusticl for consumer cards) amdgpu AMD Accelerated Parallel Processing
Intel intel-opencl-icd (Compute Runtime / NEO), part of the oneAPI stack i915 or xe Intel(R) OpenCL Graphics

For all three, the pattern is the same: install the loader (ocl-icd-libopencl1, ocl-icd-opencl-dev) once, then install the vendor runtime, then verify with clinfo. The common mistake with NVIDIA is expecting a separate OpenCL package — there is none; the OpenCL ICD lives inside the driver, so if the driver installed cleanly the ICD is already registered at /etc/OpenCL/vendors/nvidia.icd. The common mistake with AMD is confusing the ROCm compute runtime (datacentre and select consumer cards) with the Mesa rusticl path (broader consumer coverage, different maturity). Intel’s runtime is the most straightforward apt install but is easy to shadow with a stale beignet from older Ubuntu releases — remove it.

If you are targeting cross-vendor portability rather than a single card, the SDK and headers matter as much as the runtime; our guide to getting the OpenCL runtime and SDK in place for a portable compute path covers the development-side of the same stack.

Why a misconfigured environment invalidates GPU speedup benchmarks

Here is the consequence that makes this worth doing carefully. Suppose a simulation port targets a multi-day-to-hours improvement — the kind of scale where GPU acceleration is the whole point. You profile the CPU baseline, port the hot loop to OpenCL, and measure a 3× improvement. That number is either meaningful or noise, and which one it is depends entirely on whether the OpenCL runtime bound to the GPU.

If it silently ran on a CPU ICD, your “GPU” measurement is a slightly-different-CPU-path measurement. The speedup is real relative to your original code but says nothing about the GPU. Worse, it is unreproducible: change the ICD registration order on another machine and the number moves, because a different device answered the call. Every downstream decision — whether to buy the accelerator, whether the algorithm needs restructuring, whether the port is worth finishing — now rests on a baseline that measured the wrong thing.

This is why we treat the verified clinfo device listing as a gate, not a formality. The comparison of when to even choose this API is a separate decision covered in CUDA vs OpenCL when porting AI workloads; this article assumes you have made that call and now need the OpenCL environment to be provably correct before profiling.

When would I choose OpenCL over CUDA on Ubuntu?

The short version: choose OpenCL when the workload must run across more than one GPU vendor, or across GPUs and other accelerators (FPGAs, some CPUs), and you are willing to trade some NVIDIA-specific peak performance for that portability. CUDA remains the more mature single-vendor path with a deeper library ecosystem. OpenCL earns its place when vendor neutrality is a hard requirement — a media or telecom deployment that cannot assume NVIDIA silicon everywhere, for example. The full trade-off, including tooling and library maturity, is worked through in our OpenCL vs CUDA porting comparison. The setup discipline in this article applies regardless of which way that decision goes — you still have to prove the runtime reached the GPU.

FAQ

How should you think about installing OpenCL on Ubuntu in practice?

It means provisioning three separate components — the OpenCL library, the ICD loader, and a GPU vendor’s compute runtime — and confirming they agree. A single apt-get for the library resolves and reports success without any GPU runtime present, so “installed” and “running on the GPU” are different states you must verify independently.

What are the three layers of an OpenCL install — library, ICD loader, and vendor runtime — and why must they agree?

The library is the ABI you link against; the ICD loader (libOpenCL.so) dispatches calls to whichever vendor driver is registered in /etc/OpenCL/vendors/; the vendor runtime is the only layer that actually runs kernels on silicon. They must agree on version and on which device the loader selects, or you get either a hard error or, worse, a silent CPU fallback.

How do I verify with clinfo that OpenCL is actually running on my GPU and not falling back to the CPU?

Read clinfo’s device list, not its exit code. Confirm the Device Type reads GPU and the Device Name matches your actual card, count platforms with clinfo -l to catch stray ICDs, and confirm the kernel module (nvidia, amdgpu, i915/xe) is loaded. A CPU-only listing under your expected platform is the fallback trap.

What are the vendor-specific steps for installing OpenCL on Ubuntu for NVIDIA, AMD, and Intel GPUs?

NVIDIA bundles the OpenCL ICD inside the proprietary driver — there is no separate package. AMD uses ROCm’s rocm-opencl-runtime (or Mesa rusticl for broader consumer coverage). Intel uses intel-opencl-icd (Compute Runtime / NEO). In every case, install the vendor-neutral loader once, then the vendor runtime, then verify with clinfo.

Why does a silently misconfigured OpenCL environment invalidate GPU speedup benchmarks for simulation or inference workloads?

If the runtime binds to a CPU ICD instead of the GPU, your “GPU” benchmark actually measured a CPU path — a real speedup relative to your original code, but meaningless as a GPU number and unreproducible across machines with different ICD ordering. Every acceleration decision built on that baseline is then resting on a measurement of the wrong device.

When would I choose OpenCL over CUDA for a GPU compute port on Ubuntu?

Choose OpenCL when the workload must run across multiple GPU vendors or heterogeneous accelerators and you accept some NVIDIA-specific peak performance loss for that portability. CUDA is the more mature single-vendor path with a deeper library ecosystem; OpenCL wins when vendor neutrality is a hard deployment constraint.

The discipline is not the install command — anyone can run apt-get. The discipline is refusing to trust a benchmark until the clinfo device listing proves the kernel reached the silicon you meant. Get that gate wrong and you are not measuring GPU acceleration; you are measuring a CPU path wearing a GPU’s name, and the port stalls on numbers that cannot be reproduced.

Back See Blogs
arrow icon