Live data from Hacker News

New optimizations for X86 in upcoming GCC 5.0

software.intel.com

11–20 of 41 posts

Re: New optimizations for X86 in upcoming GCC 5.0

#11
post #9

Here is a more general list of gcc 5 changes https://gcc.gnu.org/gcc-5/changes.html EDIT was looking at this for __builtin_mul_overflow which apparently are in clang already, for testing overflow of arbitrary types.

Actually Clang doesn't implement the listed built-in functions (yet?). They're type-generic versions. http://llvm.org/releases/3.5.0/tools/clang/docs/LanguageExte... http://clang.llvm.org/docs/LanguageExtensions.html#checked-a...

Ah yes. The generic versions are nicer to use, and can be used for mixed types. It seems gcc will implement the clang compatible ones too.

Re: New optimizations for X86 in upcoming GCC 5.0

#12
post #8

I'm so glad to see auto-vectorization happening more and more often. However, I wonder whether a language that had built-in support for primitive floating-point vector types (e.g., GLSL's vec3, vec4, mat3, mat4) could help the compiler with performing these sorts of optimizations.

The age-old argument between "low level has less abstraction, helping the compiler" versus "high level allows you to express what you actually mean, helping the compiler"

Re: New optimizations for X86 in upcoming GCC 5.0

#13
post #7

Earlier quoted context omitted.

The article mentions two: unpacking 24 bit values and matrix multiplication, both might be something you'd find in a software video (de)compressor or a computer game

Where did you get 24 from? It's about vectorizing loads of 3 elements. The elements don't have to be 8-bit. The second example uses floats.

Yeah, but 24-bit values (RBG) are what you'd find in video and gaming applications.

Re: New optimizations for X86 in upcoming GCC 5.0

#14
post #8

I'm so glad to see auto-vectorization happening more and more often. However, I wonder whether a language that had built-in support for primitive floating-point vector types (e.g., GLSL's vec3, vec4, mat3, mat4) could help the compiler with performing these sorts of optimizations.

The age-old argument between "low level has less abstraction, helping the compiler" versus "high level allows you to express what you actually mean, helping the compiler"

High level isn't really helping, it is giving the compiler room to either screw up or shine.

It is great if the compiler shines, but frustrating if it screws up.

And yes, that applies to other tools, too. TeX, for instance, most of the time does a great job, given few specific directions, but sometimes, it doesn't quite do what you think is possible. Then, you may have a long fight ahead to make it do what you want.

Re: New optimizations for X86 in upcoming GCC 5.0

#15
post #6

Competition (with clang) is good.

People contribute to compilers because they need features or performance improvements, not "to kick that other compiler's ass". Sometimes (as here) contributions are from CPU vendors who want to make certain that compilers show off the features of their new hardware. There were tons of great performance impovements in every new version of GCC before clang, and there continue to be today. You just can't model an open source compiler the way you model some closed source word processor :(.

The real question that should be asked is whether, now with two compilers to contribute features into instead of one, whether the progress of either of the compilers is actually faster than the one previous one. Again: people aren't just not going to improve the compiler if there is only one of them, as improvements come from contributors who need the better compiler, not from some abstract notion of "have the bestest compiler". Having multiple open source projects in the same space is a detriment--it is a cost--that hopefully is justified by the benefits.

What happens in a world of "competition", is that now Intel has to ask whether it is valuable to add this feature to GCC or to clang; maybe they have time for both, but probably not. That this work ends up in one compiler and some other work ends up in a different compiler is unfortunate. It isn't even clear who is "competing" or what they are "competing" for. It certainly isn't the performance optimization itself: you can't credit the GCC team (whatever that might even mean) for that, as this work is from Intel. GCC is an open source project that is contributed to by a vast number of independent actors, not centrally developed by a small handful of people.

The argument for clang and LLVM being helpful is therefore not "competition" (which would make absolutely no sense), but instead "GCC has accumulated years of entrenched architecture that, in 2010 as opposed to 1980, we would design differently: LLVM is thereby designed in a way that is easier to modify; so, even though effort is now forked (meaning fewer contributions to each compiler), a smaller number of contributions will have a more powerful effect on the state of compilers". If this is true (and many think it is), then that's great, but it isn't "competition" in the way people normally consider that concept.

Re: New optimizations for X86 in upcoming GCC 5.0

#16
Does anyone know if -O3 (or -O2?) -march=native should be enough to get reasonable optimization for running on the same cpu as the gcc host? Or are one better off tweaking options manually (note, I know that knowing the details of how gcc works will always be better than not -- I'm just wondering if -march=native is currently considered stable/"good enough" from reasonable value of "enough" ;-)

Re: New optimizations for X86 in upcoming GCC 5.0

#17
post #16

Does anyone know if -O3 (or -O2?) -march=native should be enough to get reasonable optimization for running on the same cpu as the gcc host? Or are one better off tweaking options manually (note, I know that knowing the details of how gcc works will always be better than not -- I'm just wondering if -march=native is currently considered stable/"good enough" from reasonable value of "enough" ;-)

It's probably fine. Back in the day (early 00s) I used Gentoo and I think pretty much everyone used march (because why not?) with no real negative side effects. It may be a little more buggy with uncommon or new architectures.

I did have the occasional weird breakage with -Os, though (once it broke make...). Anyways, -O2, -O3, and -Os should be pretty reliable as I imagine they are the most used optimization flags these days.

You generally don't have to tweak options manually unless a small increase in performance is very important to your application or you are running specialized programs that will benefit largely from a specific optimization. Remember -- most Linux distributions use pretty basic cflags and are reasonably performant.

Come to think of it, the Gentoo project has probably been useful in rooting out weird cflag bugs in GCC. :)

EDIT: Also check this out:

http://wiki.gentoo.org/wiki/Safe_CFLAGS

Re: New optimizations for X86 in upcoming GCC 5.0

#18
post #14

Earlier quoted context omitted.

The age-old argument between "low level has less abstraction, helping the compiler" versus "high level allows you to express what you actually mean, helping the compiler"

High level isn't really helping, it is giving the compiler room to either screw up or shine. It is great if the compiler shines, but frustrating if it screws up. And yes, that applies to other tools, too. TeX, for instance, most of the time does a great job, given few specific directions, but sometimes, it doesn't quite do what you think is possible. Then, you may have a long fight ahead to make it do what you want.

"High level isn't really helping, it is giving the compiler room to either screw up or shine."

"It is ... frustrating if it screws up."

Re: New optimizations for X86 in upcoming GCC 5.0

#19
post #8

I'm so glad to see auto-vectorization happening more and more often. However, I wonder whether a language that had built-in support for primitive floating-point vector types (e.g., GLSL's vec3, vec4, mat3, mat4) could help the compiler with performing these sorts of optimizations.

I spent a lot of the past month improving the RenderScript (Android data-parallel compute, using C99 plus vectors) codegen to better work with the LLVM vectorizers, so I have a fair amount of experience with this exact question.

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/ )

Re: New optimizations for X86 in upcoming GCC 5.0

#20
post #16

Does anyone know if -O3 (or -O2?) -march=native should be enough to get reasonable optimization for running on the same cpu as the gcc host? Or are one better off tweaking options manually (note, I know that knowing the details of how gcc works will always be better than not -- I'm just wondering if -march=native is currently considered stable/"good enough" from reasonable value of "enough" ;-)

I think yes. A couple weeks ago I tested compilation for a project on Haswell and Sandy Bridge using various recent versions of CLang, GCC, and ICC to determine whether it was safe to use just "-O3 -march=native" in combination with "#include " instead of more specific versions.

While my testing was far from rigorous, my conclusion was that this is now sufficient and acceptable to get appropriate platform-specific SIMD optimization.

You'll find some recent arguments for "-Ofast" instead of "-O3" or "-O2", but compiler versions that don't support this are still recent enough to common. Others occasionally argue that "-Os" is a better modern default, but I haven't found this to be true. Although more debatable, I'd suggest "-g -Wall -Wextra" also be part of the defaults compiler options for most projects.

Post reply on HN