3 ms·
From the article: > These are not rock-solid results. I admit I’ve cut a lot of corners and left some room for doubt, but it looks like significant speedups ar
by vardump 11y ago
From the article:
> These are not rock-solid results. I admit I’ve cut a lot of corners and left some room for doubt, but it looks like significant speedups are possible by using explicit thread-level programming. There are optimizations that can be done at this level which are simply not possible using a conventional SPMD model.
Yeah. This is the issue with abstracting using OpenCL, CUDA, etc.
If you need absolute performance, sometimes explicit control, even if it means using SIMD intrinsics, is better than a compiler that can't understand what you are really trying to do. Of course the other side of the coins is it's more work and less portable to use explicit width intrinsics.
For example, compilers don't understand memory access patterns and it's hard to share work between execution lanes (work units).
Think of an algorithm that processes images in rectangular blocks. Each block needs also rightmost column of pixels from the block on the left. I know swizzling performed by the cache/memory controller would make this example less worse, but humor me. I'm trying to make a generic point, not just about spatial image processing.
If the order of execution is suitable, the code that computes first block could set the registers ready to transfer rightmost column of pixels for the next block on right.
So you knowing and controlling the processing order could get this single column of pixels from left of block from registers (set by previous processing of left side block), otherwise just issue one memory read for current block.
Instead of just reading both blocks again, which is what a compiler would do. Sure, it would likely come from cache. But it means more cache pressure, 95% of those pixels might not be needed anymore -- just that right edge of the left side block. In other words, in the worst case you need almost twice as much data in cache than otherwise.
> Example 1: Block Min/Max
> My first test case is taking a scalar image and computing the min and max over 4×4 tiles. This is the first half of a BC4 compressor. ...
I'm surprised first example running time dropped just from 1.7M to 1.15M. Maybe the code is cache/memory access (or some other resource, not familiar with Intel's GPUs) limited.
This might be a good place to try random evolution (genetic algorithms, monte carlo, etc.) in instruction and memory access scheduling, variations, etc. I suspect hardware level details about Intel's GPUs are not public. Some instruction stream orderings might just perform faster.
- marcosdumay 11y ago> Instead of just reading both blocks again, which is what a compiler would do. We have better compilers than that already. If you have a static data flow, there's no reason your compiler can not take it into account when optimizing your code. Optimizing a dynamic data flow is the hard one (still possible, but not done in practice), but people suck at this too.
- vardump 11y ago> We have better compilers than that already. If you have a static data flow, there's no reason your compiler can not take it into account when optimizing your code. That's right, but this is not about static data flow. This is about choosing a particular strategy for execution and caching a small amount of data in registers to maximize usefulness of cache by having less "hot memory". This reduces expensive memory traffic, which is very often the bottleneck. More generally, you can often do significant part of the work in other lane, but can't communicate this efficiently to somewhere else, because it might be executing simultaneously. So you have to for example access memory unnecessarily or do extra computation for little benefit. When you can control execution order, this is not an issue anymore. I know how amazing compilers are nowadays, but I have never seen any of them optimizing this type of case.