421 karma · joined October 29, 2010
But no, I'd never read a textbook on a Kindle. Can't flip around.
look up the target attribute and the ifunc attribute--it's basically a way to compile multiple versions of a function for different targets in a single source file and then use the dynamic linker to determine which one to resolve at runtime. obvious use is for things like optimized memcpy implementations.
GPUs for general purpose computation were never 100x faster than CPUs like people claimed in 2008 or so. They're just not. That was basically NV marketing mixed with a lot of people publishing some pretty bad early work on GPUs.
Lots of early papers that fanned GPU hype followed the same basic form: "We have this standard algorithm, we tested it on a single CPU core with minimal optimizations and no SIMD (or maybe some terrible MATLAB code with zero optimization), we tested a heavily optimized GPU version, and look the GPU version is faster! By the way, we didn't port any of those optimizations back to the CPU version or measure PCIe transfer time to/from the GPU." It was utterly trivial to get any paper into a conference by porting anything to the GPU and reporting a speedup. Most of the GPU related papers from this time were awful. I remember one in particular that claimed a 1000x speedup by timing just the amount of time it took for the kernel launch to the GPU instead of the actual kernel runtime, and somehow nobody (either the authors or the reviewers) realized that this was utterly impossible.
GPUs have more FLOPs and more memory bandwidth in exchange for requiring PCIe and lots of parallel work. if your algorithm needs those more than anything else (like cache), can minimize PCIe transfer time, and handles the whole massive parallelism thing well, then GPUs are a pretty good bet. If you can't, then they're not going to work particularly well.
(now, if you need to do 2D interpolation and can use the texture fetch hardware on the GPU to do it instead of a bunch of arbitrary math... yeah, that's a _huge_ performance increase because you get that interpolation for free from special-purpose hardware. but that's incredibly rare in practice)
http://graphics.cs.cmu.edu/courses/15869/fall2014/ http://15418.courses.cs.cmu.edu/spring2014/
The vector types help in some ways--if you can use only vectors and do arithmetic on entire vectors only the SIMD codegen already works great--but they don't really help more than an intelligent vectorizer could. For example, the LLVM loop vectorizer can only handle loops where the induction variable changes by 1 or -1 each iteration. As a result, you couldn't set A[i], A[i+1], and A[i+2] in a for loop where i += 3 each iteration. If you could do that, you wouldn't really need vec3 in the first place. (also, the presence of any vector types whatsoever prevent any vectorization in LLVM right now, so...)
Another issue is that using vectors for storage and vectors for computation are very different things. I don't think anyone actually likes using vectors for computation, but vectors for storage make a lot of sense in some fields like image processing. However, as soon as you start operating on single channels, things get messy. Let's say you have a for loop where each iteration operates on a float4 as individual channels. Let's also say you want to turn each of those single channel operations into its own float4 operation, vectorizing across four iterations of the loop. Given most current SIMD ISAs, you're going to have to do four 32-bit loads of A[i].x, A[i+1].x, etc., then pack that into a vector, do your arithmetic ops, unpack the vector, and do four 32-bit writes to memory. Unsurprisingly, this is not particularly fast, and if you're doing one mul or FMA per channel, you shouldn't be vectorizing at all. This is why you see cost models in vectorizers (to prevent this sort of packing/unpacking from killing your performance when you enable your vectorizer) as well as why you see newer SIMD ISAs like AVX2 in Haswell including support for scatter/gather and permute.
The last issue is that it's trivial to break a vectorizer because of easy to overlook things like ailasing. Missing a single restrict will prevent vectorization if the compiler can't prove that pointers won't alias, for example (why do you think people still use fortran in HPC?). There's actually been a lot of great work here in LLVM over the past few months with new aliasing metadata for LLVM IR (http://llvm.org/docs/LangRef.html#noalias-and-alias-scope-me...), which is what I used to make the SLP vectorizer work with RenderScript in a way similar to ISPC (except in the compiler back end instead of the front end, because we don't even know the target ISA at the time the RS source is compiled to LLVM IR). I'll probably get the patch in AOSP in the next week or two if you want to keep an eye on that; it needs a newer LLVM version than what shipped in L and we're finishing up that rebase.
(honestly, I think that if you're trying to get good server CPU performance and you know exactly what CPU you're going to be using at compile time, you should be looking at ispc instead of doing SSE intrinsics yourself: https://ispc.github.io/ )
This was attempted. It failed: http://en.wikipedia.org/wiki/OpenGL#Longs_Peak_and_OpenGL_3....
Mobile: GPU has 3-5x the FLOPs of the CPU and no bandwidth advantage because of the shared memory pool between CPU and GPU. GPUs have very wide ranges of functionality. Even the CPUs behave very differently (Krait in Nexus 4 sometimes chews through code that the A15 in Nexus 10 chokes on and vice-versa). What comprises a system varies tremendously--CPU, CPU + GPU, CPU + GPU + other processors, etc.
A developer shouldn't be expected to have to tune for 20 different processors and system architectures in order to ship an app on the Android market. That's the problem we're trying to solve, not simply exposing access to GPU compute.
Basically, he gives us too little credit for the execution model (it's young, it's improving very quickly and is not at all designed to emulate anything else that exists today) and assumes that GPU compute has the same tradeoffs on mobile as desktop (it doesn't at all). You'll see more from us soon.
Of course, this would have worked a lot better if people cared about WinRT at all, but I'm sure that was the idea.
If you think your existing MPI app is going to automatically scale to a heterogeneous architecture (high-power x86 on the main CPU, Xeon Phi cores on the accelerator) and get acceptable performance, sorry, it's not going to happen.
The fundamental constraints on 2012/2013 Xeon Phi performance that determine how apps should be written are exactly the same as current desktop GPUs (small, high-latency local memory that is not coherent with the rest of the system; relatively slow, high-latency link to CPU; ugly interactions with network cards in most environments; fundamental need to hide memory latency at all times). For any sort of performance beyond a standard Xeon, you're going to want to run a Xeon Phi as a targeted accelerator rather than offloading entire processes to it and using a standard MPI stack. This means you're going to be running in a hybrid host/device mode and using compiler directives or a specific parallel language and API to deal with on-chip execution and data transfer, which puts you in exactly the same solution space as with GPUs.
in other words: the Phi of today is not a panacea. you get better tools and more flexibility in terms of the programming model, but the fast path that any of its intended market would use in applications looks identical to GPUs.
(I'm a C programmer, I don't look at assembly that often at all, but it's certainly helpful to be able to do so and my knowledge of the x86 ISA, calling conventions, etc has informed many decisions I've made in the past, especially re: performance)
Current Intel CPUs have a very small GPU built on to the die of the CPU. By buying the CPU, you're paying for an Intel GPU anyway.
At the same time, unlike CPU performance, GPU performance really does scale with die area; if you want more graphics performance, get a bigger chip with more ALUs/texture units/etc, and because graphics is so parallel everything will just go faster. However, larger chips mean larger amounts of leakage when the chip is powered but idle, which means that battery life can be significantly worse.
What Optimus does is allow the Intel GPU to be connected to the display hardware and be used most of the time (e.g., when you're looking at email or whatever) when high performance isn't called for. At that point, the NVIDIA GPU can be turned off completely, meaning no leakage and no battery life degradation. If you want high performance, the NVIDIA GPU is enabled on the fly, rendering is done on the NVIDIA GPU, and the final result is sent in some way to the Intel GPU, which can then use its actual display connections to put something on the LCD.
Prior to Optimus, there was generally a mux that would switch which GPU was outputting to the screen. This was messy because everything had to be done on one GPU or the other, it was noticeably heavyweight, occasionally required reboots, increased hardware complexity, etc.
The biggest issue with Optimus on Linux is that the infrastructure for the actual sharing of the rendered output didn't really exist until dmabuf appeared--you need two drivers to be able to safely share a piece of pinned system memory such that they can both DMA to/from that memory and be protected from any sort of bad behavior from each other. (I also think it's impossible to have two different drivers sharing the same X screen, which is why bumblebee works the way it does)
Users generally won't understand the implementation of the API, so instead they build a model of how they think the entire system operates. In the process, they make assumptions about performance, side effects, etc. that may be totally incorrect. Good APIs anticipate these assumptions and make them relatively easy to predict with some level of experience, either from elsewhere in the API or from similar APIs.
http://www.anandtech.com/show/5770/lava-xolo-x900-review-the...