A green checkmark from clinfo is the moment most OpenCL installs are declared done. It is also the moment the real problem starts to hide. On a GPU/CPU video pipeline, the install you choose decides whether you can even measure the handoff costs between stages — and a clinfo that lists a device tells you almost nothing about whether the pipeline will actually run there. The naive setup is short and satisfying: install a single ICD, run clinfo, see a device name, ship it. What that sequence quietly skips is verification. It confirms that an OpenCL platform exists, not that the platform your decode-analyse-encode pipeline binds to at runtime is the GPU you paid for. We see this pattern regularly on Ubuntu hosts destined for broadcast and video-analytics workloads: the install “works,” the pipeline runs, and throughput numbers come back looking oddly like CPU numbers because that is exactly what they are. What does installing OpenCL on Ubuntu actually mean? OpenCL on Linux is not one thing. It is a loader plus one or more implementations, and the loader is the piece people forget to reason about. The ICD loader (libOpenCL.so, packaged as ocl-icd-libopencl1 on Ubuntu) is a thin dispatch layer. When your application calls clGetPlatformIDs, the loader reads the .icd files under /etc/OpenCL/vendors/, dlopens each vendor runtime listed there, and enumerates whatever those runtimes report. The loader does not compute anything. The vendor runtime does. So “install OpenCL” decomposes into three separate decisions, and conflating them is the root of most misconfigured stacks: The ICD loader — the dispatch library your application links against. The vendor runtime (the ICD) — the actual OpenCL implementation for a specific device: NVIDIA’s, an Intel/AMD driver, or a portable runtime. Device selection — which platform and device your code binds to at runtime, out of everything the loader enumerated. The trap is that all three can be present and still be wrong for your pipeline. A host can carry the NVIDIA ICD, the Portable Computing Language runtime that many packages pull in as a CPU fallback, and an Intel driver simultaneously. clinfo will happily list all of them. Your pipeline binds to the first platform that satisfies its device query — and if that query is loose, it may land on the CPU implementation while you believe you are on the GPU. Which OpenCL packages do you actually need? For a GPU/CPU video pipeline on Ubuntu, the minimum viable set is the loader plus exactly the vendor runtime for your target device — and a deliberate decision about whether a CPU fallback runtime should be installed at all. The decision table below is the one we reach for when scoping an install on a fresh Ubuntu host. Package decision table Component Package (Ubuntu) Install when Watch out for ICD loader ocl-icd-libopencl1 Always — every setup needs one loader Multiple loaders (Khronos vs ocl-icd) coexisting; pick one Headers / dev opencl-headers, ocl-icd-opencl-dev Building OpenCL code on the host Header/runtime version mismatch NVIDIA runtime ships with the NVIDIA driver Targeting an NVIDIA GPU Driver install that omits the OpenCL ICD file Intel GPU runtime intel-opencl-icd Targeting Intel integrated/discrete GPU Wrong compute-runtime version for the silicon AMD (ROCm) runtime ROCm OpenCL runtime Targeting AMD data-centre GPU ROCm/kernel version pinning Portable CPU runtime pocl-opencl-icd Only when you want a CPU path Installed unintentionally, becomes silent fallback Diagnostics clinfo Always — verification tool Treating its output as proof of runtime binding Evidence class for the “watch out for” column: observed-pattern across TechnoLynx GPU-audit engagements on Ubuntu hosts — not a published benchmark, but a repeatable failure surface we have learned to check first. The single most common mistake is on the last row. Something in the dependency graph — a media library, a diagnostic tool, a scientific package — pulls in pocl-opencl-icd, which registers a fully functional CPU OpenCL platform. Now the host has a device that answers every OpenCL query, works flawlessly, and produces correct output at a fraction of the throughput you expected. Nothing errors. That is precisely why it is dangerous. Our sibling walkthrough on installing OpenCL on Ubuntu for GPU video-analytics workloads goes deeper on the driver-side packaging; this article’s job is the verification discipline that comes after packages land. How do you verify the pipeline will target the intended device? clinfo enumerates. It does not bind. To verify, you have to ask two separate questions: what platforms exist and what platform will my pipeline actually choose. Answering only the first is the error at the heart of the naive approach. Start with enumeration: clinfo -l If you see more than one platform — say, NVIDIA CUDA and Portable Computing Language — that is the moment to stop and decide which one your pipeline should bind to, not the moment to declare success. A single-line summary makes the ambiguity visible in a way the full clinfo dump buries. Then verify binding. The honest test is not clinfo; it is your pipeline’s own device selection, made explicit. In practice this means the application should log the platform and device it selected, and that log line should name the GPU. If your OpenCL code selects a device by taking platforms[0] without inspecting CL_DEVICE_TYPE, it is gambling on enumeration order. Query CL_DEVICE_TYPE_GPU explicitly, and fail loudly if no GPU device is found rather than falling back to CPU silently. Device-verification checklist clinfo -l shows exactly the platforms you expect — no unplanned CPU runtime. The vendor .icd file exists under /etc/OpenCL/vendors/ and points at a runtime that loads. Your application logs the selected platform and device name at startup. Device selection filters on CL_DEVICE_TYPE_GPU, not enumeration order. A run on a host with the GPU driver removed fails, rather than silently succeeding on CPU. That last check is the one people resist and the one that pays off. If your pipeline still runs after you remove the GPU runtime, it was never bound to the GPU. This is the same underutilisation pattern that a misconfigured runtime produces on any accelerated workload — a concrete cause we point to when ruling out GPU underutilisation during an audit. What install mistakes cause silent CPU fallback or redundant copies? Two failure classes dominate, and they compound each other. The first is silent CPU fallback, covered above: a CPU ICD is present, device selection is loose, and work reroutes without an error. The pipeline is correct and slow, which is the worst combination because correctness masks the cost. The second is redundant host-device copies. Even when you bind to the GPU correctly, an install that ignores shared-memory paths forces every stage boundary to round-trip buffers through host memory. On a decode-analyse-encode chain, that means the decoded frame is copied to host, copied back to device for analysis, copied to host again, copied back for encode — four transfers where a shared buffer needs zero or one. The frames are on the GPU; the copies are pure overhead. This is exactly the host-device copy latency that stage-boundary profiling is supposed to expose, and it stays hidden if the runtime cannot report it honestly. Confirming shared-memory paths at install time is what keeps those copies measurable. On integrated GPUs, that means verifying the runtime advertises CL_DEVICE_HOST_UNIFIED_MEMORY and that your allocation strategy uses CL_MEM_ALLOC_HOST_PTR or CL_MEM_USE_HOST_PTR where a zero-copy path exists. On discrete GPUs, it means confirming the runtime and PCIe topology support the pinned-memory transfers your profiler will attribute to the copy budget. Get this wrong and the copies still happen — you simply lose the ability to see them, which turns a profiling exercise into guesswork. Why is a verified install a precondition for honest profiling? This is the claim that reframes the whole exercise. A GPU Performance Audit measures stage-boundary costs: how much time and bandwidth each handoff between decode, inference, and encode actually consumes. Those measurements are only meaningful if the runtime they run against is the runtime you will deploy. If the audit runs against a stack where OpenCL silently fell back to CPU, or where shared-memory paths were unavailable and every boundary round-tripped through host memory, the copies and stalls it records are stack artifacts, not economics. Put plainly: a working clinfo is not a working pipeline. The verification steps above are not hygiene for its own sake — they are the precondition for reading GPU utilisation as a true signal rather than a buy-signal. When the ICD loader, vendor runtime, and device selection are all verified, the profiled copy and stall costs match the deployed hardware, and acceleration decisions rest on real numbers. The same discipline underpins the stage-economics reasoning we walk through for GPU/CPU stage economics on inference pipelines, where a mismeasured handoff can flip a hardware decision the wrong way. For broadcast and video-analytics teams standing up new Ubuntu hosts, this is why the install belongs in the same conversation as the profiling work rather than being treated as a prerequisite to rush through — see how it fits the broader media and telecom broadcast pipeline. FAQ How does installing OpenCL on Ubuntu work in practice? Installing OpenCL on Ubuntu means installing an ICD loader (ocl-icd-libopencl1) plus one or more vendor runtimes that register .icd files under /etc/OpenCL/vendors/. The loader dispatches your application’s OpenCL calls to whichever runtimes those files point at. In practice it is three decisions — loader, runtime, and device selection — not a single package, and treating it as one package is where misconfigured stacks begin. Which OpenCL packages, ICD loader, and vendor runtime do you actually need on Ubuntu for a GPU/CPU video pipeline? You need exactly one ICD loader (ocl-icd-libopencl1), the vendor runtime for your target device (NVIDIA ships its runtime with the driver; Intel uses intel-opencl-icd; AMD uses the ROCm OpenCL runtime), and clinfo for diagnostics. A CPU runtime like pocl-opencl-icd should be installed only when you deliberately want a CPU path — installed unintentionally it becomes a silent fallback. How do you verify with clinfo that the pipeline will target the intended device rather than a CPU fallback? Run clinfo -l to list platforms and confirm you see only the ones you expect. Then verify binding, not just enumeration: have the application log its selected platform and device, filter device selection on CL_DEVICE_TYPE_GPU, and fail loudly if no GPU is found. The decisive test is removing the GPU runtime — if the pipeline still runs, it was never bound to the GPU. What common install mistakes cause silent CPU fallback or redundant host-device copies? The first is a CPU ICD (often pulled in as a dependency) combined with loose device selection, so work reroutes to CPU without any error. The second is ignoring shared-memory paths, which forces every stage boundary to round-trip buffers through host memory. Both are correct-but-costly failures that produce no error message, which is why they hide. Why is a verified OpenCL install a precondition for honest stage-boundary profiling in a GPU Performance Audit? A GPU Performance Audit measures the copy and stall costs at each handoff between decode, inference, and encode. Those measurements only mean something if the runtime under test is the runtime you deploy. If OpenCL silently fell back to CPU or shared-memory paths were unavailable, the recorded costs are stack artifacts rather than real economics, and the audit’s conclusions inherit the misconfiguration. How do you confirm shared-memory paths so host-device copy costs stay measurable? On integrated GPUs, verify the runtime advertises CL_DEVICE_HOST_UNIFIED_MEMORY and use CL_MEM_ALLOC_HOST_PTR or CL_MEM_USE_HOST_PTR where a zero-copy path exists. On discrete GPUs, confirm the runtime and PCIe topology support pinned-memory transfers your profiler can attribute to the copy budget. Getting this wrong does not stop the copies — it stops you from seeing them. How does the OpenCL runtime you install affect the acceleration-discord picture the parent hub describes? The acceleration-discord picture depends on comparing what the hardware could deliver against what the pipeline actually achieves. A runtime that silently reroutes work to CPU or hides host-device copies makes that comparison meaningless, because measured utilisation no longer reflects the deployed device. The right install turns the runtime into honest instrumentation, so the discord you observe is real rather than an artifact of the stack. Where this leaves the setup Treat the install as the first measurement, not a chore that precedes measurement. The question worth carrying forward is not “does clinfo see a device” but “can I prove, by removing the GPU runtime, that my pipeline was bound to it” — and if that proof fails on a host you have already profiled, every stage-boundary number you collected is suspect. That failure class, silent CPU fallback masquerading as a working install, is exactly what a GPU Performance Audit scoped to video-analytics workloads exists to catch before it reroutes an acceleration decision.