Hello, and welcome to C++ Weekly.
I'm your host, Jason Turner.
I'm available for code reviews, contracting,
and on-site training.
Now, in this episode of C++ Weekly,
I am going to talk about getting factorization of our code
automatically from the compiler.
Now, I'm not going to dig into the very gory details of all
of this.
But I want to point out a couple of things
that you may not be aware of and a couple things
that I tend to personally not think of when
I am compiling my own code.
So let's just do a very simple function that
sums some integers.
And of course, there's an algorithm
that we can use for this.
So we are going to.
And we have to include the requisite headers.
And I guess technically, it's worth
pointing out that accumulate is not an algorithm.
It is in the numeric header-- or though,
maybe that means it's just an algorithm that's
in the numeric header.
But it's definitely not in the algorithm header.
So I am compiling with dash 03 here, with Clang.
And it is doing something, some factorization here.
But it's doing it kind of at a simpler level, if you will.
So what you need to do, if you want it to take advantage
of the latest SSE instructions-- and that's really what
I'm trying to get at here--
is tell it that you've got some sort of CPU that
has SSE instructions.
So I've just it m arc equals native.
Now, I know that this is not the suggested way to do this.
Because on Compiler Explorer, you
have no idea what kind of CPU this is actually compiling on.
There are several different architectures
that are in use by the back end of Compiler Explorer.
So we've just got some random CPU's native instruction set.
But we can see that it is using these instructions that
are extremely long and difficult to pronounce
and don't really follow this kind of easy mnemonics
that the assembly world originally had,
where things were just a few letters
and it made perfect sense.
These are things that, like I said, are very long.
But it went to doing these vectorized instructions.
So let's make a couple more compilers,
and we can compare the outputs.
With the Clone Compiler tool here, I can come in
and I can remove the native flag.
And we can see the difference here
between the vector instructions and these.
And then we can also come in and add a Visual Studio compiler--
latest version of Visual Studio that's available on here.
Now, of course.
Visual Studio's CL dot exe has different command line options
than Clang and GCC do.
It's got its own pedigree, if you will.
Clang was written intentionally to be command
line compatible with GCC.
But that relationship does not exist between GCC and Visual
Studio.
I'm going to break this one out so that we can see this.
Now, there's definitely more going on on the Visual Studio
compiler output.
This is not really the fault of Visual Studio
or of Compiler Explorer.
It's just the nature of the thing here.
That dead code is not removed.
So we care about this code right here, the thing at the top.
And we can see that it's basically not doing any
optimizations at all, even though we've got dash 02 here--
dash 03, that is.
And that's because dash 03 is not a compiler option with
Visual Studio.
Now, forward slash capital 02 is the recommended way of saying I
want all of the optimizations available on Visual Studio
today.
And we can see, it's kind of doing something pretty similar
to the dash 03 of Clang down here,
with a little bit of short circuiting out
on the summation.
So how do we get the vectorization
that we want with Visual Studio's compiler?
And that is by adding the AVX switch.
So at the moment, as far as I understand it,
this is basically state of the art for Visual Studio.
We say, 02, we want all of the optimizations.
AVX 2 says, use all of the latest CPU instructions.
And now we can see also that Visual Studio
is using these same vectorizer instructions.
And it's using a different register set.
But I don't know enough about what it's doing right there.
But I just wanted to make everyone aware
that you need to tell the compiler about the architecture
that you intend to run this code on if you want it to take
advantage of the architecture that you're
running the code on.
So make sure that you're paying attention to this,
know what your minimum deployment requirements are,
and make sure that you're doing the right thing.
The Visual Studio options are pretty straightforward.
But we can actually go and take a look
at the full list of architectures
supported by GCC and Clang.
So with GCC and Clang, you can pass the architecture
two different ways.
You have this mtune option that says,
I want to be tuned to a specific CPU architecture.
Or you can use march, and you can say,
I want this specific CPU architecture.
And then you're basically telling it,
I want something that's got SSE, and AVX,
and all of the possible options.
And to be fair, I probably misspoke
when I said something about which specific registers were
being used.
There's an absolutely huge range of things
that are available here.
And you can see, even to the specificity here,
that this says, well, this particular CPU
supports these operations, like move be and that kind of thing.
And we can tell it which architecture
we're using to get the most out of that particular CPU family
that we plan to deploy to.
So particularly if performance is critical to you,
make sure that you are building the code specifically
for the systems that you know that you're going to deploy to.
So thanks for watching this episode,
and I hope you learned something.