Live data from Hacker News

Implementing a GPU's programming model on a CPU

litherum.blogspot.com

51–60 of 61 posts

Re: Implementing a GPU's programming model on a CPU

#51
post #9

Isn't this already implemented in QEMU?

No, QEMU only supports up to AVX2. Based on the time it took to implement AVX and AVX2, I expect it would be about a month of full time work to implement AVX512F, AVX512BW and AVX512VL (it would not be much simpler to implement only one of them).

Re: Implementing a GPU's programming model on a CPU

#53

I helped make a really cursed RISC-V version of this for a class project last year! The idea was to first compile each program to WASM using clang, and lower the WASM back to C but this time with all opcodes implemented in terms of the RISC-V vector intrinsics. That was a hack to be sure, but a surprisingly elegant one since 1. WASM's structured control flow maps really well to lane masking 2. Stack and local values…

This is cool! If you wrote a blog post going detail about the insights, I'd read it

The linked github page has a link to a paper.

Re: Implementing a GPU's programming model on a CPU

#55
post #35

Earlier quoted context omitted.

SIMT let's a scheduler get clever about memory accesses, SIMD can practically only access memory linearly (scatter gather can do better but it's still usually quite linear) whereas SIMT can be much smarter in terms of having lots of similar bits of work going on in ways that use the bandwidth maximally and don't overlap.

https://developer.nvidia.com/blog/how-access-global-memory-e... SIMT still expects coalesced memory access that's close together otherwise performance falls off a cliff

Yes, but not all thread in the block need to. As long as you fill a cache line you’re good.

Re: Implementing a GPU's programming model on a CPU

#56

I helped make a really cursed RISC-V version of this for a class project last year! The idea was to first compile each program to WASM using clang, and lower the WASM back to C but this time with all opcodes implemented in terms of the RISC-V vector intrinsics. That was a hack to be sure, but a surprisingly elegant one since 1. WASM's structured control flow maps really well to lane masking 2. Stack and local values…

I don't know that I'd ever use this in production but this is really really cool. Nice work.

Re: Implementing a GPU's programming model on a CPU

#57
post #3

See also: https://ispc.github.io/

ISPC is great software. It's a shame in many ways Intel didn't put more resources behind it.

I naively thought ISPC turned into the new DPCPP compiler they’re leaning into with their oneAPI marketing. Are those really different lineages?

Re: Implementing a GPU's programming model on a CPU

#58
post #7

This so-called GPU programming model has existed many decades before the appearance of the first GPUs, but at that time the compilers were not so good like the CUDA compilers, so the burden for a programmer was greater. As another poster has already mentioned, there exists a compiler for CPUs which has been inspired by CUDA and which has been available for many years: ISPC (Implicit SPMD Program Compiler), at https:/…

SIMT and SIMD are different things. It's fortunate that they have different names. A GPU is a single instruction multiple data machine. That's what the predicated vector operations are. 32 floats at a time, each with a disable bit. Cuda is a single instruction multiple thread language. You write code in terms of one float and branching on booleans, as if it was a CPU, with some awkward intrinsics for accessing the ve…

> SIMT and SIMD are different things.

was anything said against that?

the comment said SIMT is same as SPMD

Re: Implementing a GPU's programming model on a CPU

#59

Earlier quoted context omitted.

SIMT and SIMD are different things. It's fortunate that they have different names. A GPU is a single instruction multiple data machine. That's what the predicated vector operations are. 32 floats at a time, each with a disable bit. Cuda is a single instruction multiple thread language. You write code in terms of one float and branching on booleans, as if it was a CPU, with some awkward intrinsics for accessing the ve…

> It's not totally clear to me why simt won out over writing the vector operations. From the user side, it is probably simpler to write an algorithm once without vectors, and have a compiler translate it to every vector ISA it supports, rather than to deal with each ISA by hand. Besides, in many situations, having the algorithm executed sequentially or in parallel is irrelevant to the algorithm itself, so why introdu…

I think it's easier to write the kernel in terms of the scalar types if you can avoid the warp level intrinsics. If you need to mix that with the cross lane operations it gets very confusing. In the general case volta requires you to pass the current lane mask into intrinsics, so you get to try to calculate what the compiler will turn your branches into as a bitmap.

So if you need/want to reason partly in terms of warps, I think the complexity is lower to reason wholly in terms of warps. You have to use vector types and that's not wonderful, but in exchange you get predictable control flow out of the machine code.

Argument is a bit moot though, since right now you can't program either vendor hardware using vectors, so you also need to jump the barrier to assembly. None of the GPUs are very easy to program in assembly.

Re: Implementing a GPU's programming model on a CPU

#60

Earlier quoted context omitted.

SIMT and SIMD are different things. It's fortunate that they have different names. A GPU is a single instruction multiple data machine. That's what the predicated vector operations are. 32 floats at a time, each with a disable bit. Cuda is a single instruction multiple thread language. You write code in terms of one float and branching on booleans, as if it was a CPU, with some awkward intrinsics for accessing the ve…

I guess that a lot of people are uncomfortable thinking about vector instructions, and dealing with masks manually? And for vector instructions you need to align things properly, pad the arrays such that they are of the right size, that people are not used to I guess.

I agree. I work on numerical simulation software that involves very sparse, very irregular matrices. We hardly use SIMD because of the challenges of maintaining predicates, bitmasks, mapping values into registers, and so on. It's not bad if we can work on dense blocks, but dealing with sparsity is a huge headache. Now that we are implementing these methods with CUDA using the SIMT paradigm, that complexity is largely taken care of. We still need to consider how to design algorithms to have parallelism, but we don't have to manage all the minutiae of mapping things into and out of registers.

Modern GPGPUs also have more hardware dedicated to this beyond the SIMD/SIMT models. In NVIDIAs CUDA programming model, besides the group of threads that represents a vector operation (a warp), you also have groups of warps (thread blocks) that are assigned the same processor and can explicitly address a fast, shared memory. Each processor has many registers that are automatically mapped to each thread so that each thread has its own dedicated registers. Scheduling is done in hardware at an instruction level so that you can effectively single cycle context switches between warps. Starting with Volta, it will even assemble vectors from threads in any warps in the same thread block, so lanes that are predicated off in a warp don't have to go to waste - they can take lanes from other warps.

There are many other hardware additions that make this programming model very efficient. Similar to how C and x86 each provide abstractions over the actual micro ops being executed that hides complexity like pipelining, out of order execution, and speculative execution, CUDA and the PTX ISA provide abstractions over complex hardware implementations that specifically benefit this kind of SIMT paradigm.

Post reply on HN