Looking at 2 more C compiler options (-fpeel-loops & -funsafe-math-optimizations)

Here’s two more C compiler options I looked at. Hold on to the edge of your seats folks.

-fpeel-loops

Definition from the GNU man page:

Peels the loops for that there is enough information that they do not roll much (from profile feedback). It also turns on complete loop peeling (i.e. complete removal of loops with small constant number of iterations).

Essentially, this option is one way to optimize for-loops by “peeling”. Peeling is the action of splitting the first or last few iterations from a loop and running them outside of the loop body. It is enabled with the -fprofile-use option, which allows the compiler to “profile” your code by reading it multiple times with feedback to learn how to optimize it optimally.

Here is an example of how peeling works.

BEFORE PEELING:
int p = 10;
for (int i=0; i<10; ++i) {
y[i] = x[i] + x[p];
p = i;
}

You can see p = 10 only for the first iteration. For the rest of the iterations, p = i – 1. Therefore, the first iteration can be “peeled”.

AFTER PEELING:
y[0] = x[0] + x[10];
for (int i=1; i<10; ++i){
y[i] = x[i] + x[i-1];
}

By peeling, we have eliminated the need for the variable p, which increased performance.

In summary, -fpeel-loops will optimize loops and increase your build time, but decrease run time. Therefore, it is useful in situations where run time is more important than the build time such as if the program will be distributed to users and consumers.

-funsafe-math-optimizations

Definition from the GNU man page:

Allow optimizations for floating-point arithmetic that (a) assume that arguments and results are valid and (b) may violate IEEE or ANSI standards. When used at link-time, it may include libraries or startup files that change the default FPU control word or other similar optimizations.

This option should never be turned on by any -O option since it can result in incorrect output for programs which depend on an exact implementation of IEEE or ISO rules/specifications for math functions.

The default is -fno-unsafe-math-optimizations.

As the title states, this options makes some “unsafe math optimizations” – specifically with floating-point arithmetic. Seems unsafe right? It depends. Are you a mad rocket scientist trying to blow up an asteroid with laser beams where the tiniest of fractions and signed and unsigned zeroes could destroy the earth instead? Me neither. So you’re probably okay to use it. You may lose a few tiny decimal points, but if strictly adhering to  IEEE/ANSI standards or being extremely precise isn’t important, then it won’t matter. So to hell with unsafe. Go ahead and try it. Maybe compare the output to make sure though…

Looking at 2 more C compiler options (-fpeel-loops & -funsafe-math-optimizations)

Analyzing the effects of basic C compiler options

In this post I’ll talk about the effects of some basic C compiler options I tried out.

 

The C program I used was a bare-bone Hello World as shown:

#include <stdio.h>

int main() {
printf(“Hello World!\n”);
}
 

-g -O0 -fno-builtin

The program was first compiled with the -g, -O0, and -fno-builtin options.
Below is a quick summary of what each option does.

-g               # enable debugging information
-O0              # do not optimize (that’s a capital letter and then the digit zero)
-fno-builtin     # do not use builtin function optimizations

Here is the run time, file size, and the main() section of the objdump binary ELF (Executable and Linkable Format).

Time
real      0m0.113s
user     0m0.032s
sys       0m0.004s

Size
9592 bytes

ELF
0000000000400536 <main>:

#include <stdio.h>

 

int main() {

400536:         55                   push   %rbp

400537:         48 89 e5                      mov    %rsp,%rbp

printf(“Hello World!\n”);

40053a:         bf d4 05 40 00             mov    $0x4005d4,%edi

40053f:          b8 00 00 00 00            mov    $0x0,%eax

400544:         e8 c7 fe ff ff                callq  400410 <printf@plt>

}

400549:         b8 00 00 00 00            mov    $0x0,%eax

40054e:         5d                   pop    %rbp

40054f:          c3                   retq

Awesome. The ELF looks like gibberish, but it means stuff. Let’s move on.

-static added

The option -static was added.

-static prevents linking with the shared libraries and links a program statically instead. This means any library required will be completely written into the executable. In turn, this means that your executable will obviously be bigger with the big increase in code. The size before 9592 bytes as you saw without -static and became 883200 bytes after.
So why would you use -static? Speed at run time. Dynamic linking takes more time than having everything already statically in the executable. If you desire run time speed over executable size, -static may be a useful option.

-fno-builtin removed

The option -fno-builtin was removed from the original set of options.

As explained earlier, having this option on disables certain builtin function optimizations. Therefore, removing it allowed optimization on the printf() function using a puts instead of printf, which will be more efficient. See the differences in the main section of the ELF.

WITH -fno-builtin

printf(“Hello World!\n”);

40053a:         bf d4 05 40 00             mov    $0x4005d4,%edi

40053f:          b8 00 00 00 00            mov    $0x0,%eax

400544:         e8 c7 fe ff ff                callq  400410 <printf@plt>

WITHOUT -fno-builtin

printf(“Hello World!\n”);

40053a:     bf d4 05 40 00               mov    $0x4005d4,%edi

40053f:     e8 cc fe ff ff                  callq  400410 <puts@plt>

-g removed

-g provided debugging information. So remove it and you get fewer headers, your file size gets a little smaller, and it should compile a little quicker. The size goes down from 9592 bytes to 8560 bytes. The run time goes down from 0m0.113s to  0m0.053s. So it’s not a huge difference, but if you don’t need to debug, I guess -g is unnecessary.

Additional arguments added to the printf() function

Arguments were added like below.

#include <stdio.h>

int main() {
int a = 0;
int b = 1;
int c = 2;
int d = 3;
int e = 4;
int f = 5;
int g = 6;
int h = 7;
int i = 8;
int j = 9;
 
printf(“Hello World! %i %i %i %i %i %i %i %i %i %i \n”, a, b, c, d, e, f, g, h, i, j);
}

There’s supposed to be a pattern in which register each argument is placed in. But I haven’t figured it out yet. I’ll come back with an edit on this one;) If you figure it out, let me know.

Moved printf() call to a seperate function named output()

Here’s the new code.

#include <stdio.h>

void output(char str[] ){
printf(“%s”, str);
}
 
int main() {
char c[50] = “Hello World!\n”;
output(c);
}

The purpose of rewriting it this way was to see what the changes were in the object code. Essentially output() got its own section and could be seen being called from the main section.

Replace -O0 with -O3

I swear I’ll stop boring you. The last compiler option tested was to see how -O0 and -O3 differentiated. -O0 (the default if no -O is specified) means don’t optimize at all. The compiler time should be faster with -O0 since it has no optimizing to do. -O3 is the highest and most aggressive level of optimization turning on a big group of optimization options. The compilation time will be increased and more memory might be used, but performance should increase as well.

 

 

 

 

 

 

Analyzing the effects of basic C compiler options

Contributing to open source software packages

A little late to the game, but excited to begin!

This post will briefly speak of two open source software packages that anybody can contribute to and how it can be done.

Bitcoin

The digital currency of the future – spawning hilarious, yet non-trivial branch-offs like dogecoin, is in fact open source. Released under the terms of the MIT license, Bitcoin, can be developed by anybody willing to contribute. Here’s how.

  1. Visit their GitHub repository. There, you can see all the development ideas and discussions taking place.
  2. To contribute a patch proposal, make a “pull request” abiding to the specified rules and guidelines.
  3. Wait for others to comment and review your proposal.
  4. (3.5?) While waiting, help review others’ pull requests. Also, sign up for the developer mailing list to discuss more complicated and controversial ideas.
  5. If thoroughly review and approved, project maintainers will merge the pull request.
  6. Finally, the project leader will O.K. each Bitcoin release.

And that’s it.

How hard is it to get a patch accepted? How long will it take? Well, that depends. Firstly, open source means contributors work on their own time. So review times can vary widely. Secondly, if the patch is very minor and simple, there probably won’t need to be much discussion. But if the patch is complicated and controversial, it will take much longer and require more reviews and reviewers.

In summary, Bitcoin’s GitHub method of contributing seems like a fairly democratic and organized way to open source and build software. One tiny kink may be that the project maintainers and leaders may have unequal power in what gets merged or not. But you need some kind of system. So…hopefully they are fair. And not stupid.

Gimp

GIMP (GNU Image Manipulation Program), released under GNU GPLv3+ licence, does things quite a bit differently than Bitcoin. Although also open source, GIMP development is managed by a team of specific developers. Here is how to contribute patches to GIMP.

  1. Look through the bug reports in GNOME Bugzilla that you could work on.
  2. This step is important for GIMP. Contact the GIMP team first about the patch you want to make. Somebody else may already by working on the patch, or the idea may not be relevant to the direction of GIMP.
  3. Once approved, submit the bug report with the patch and appropriate documentation attached.
  4. The GIMP team will review then potentially merge the patch on their git server.
  5. Wait for further communication with the GIMP team.

So a much more behind-closed-doors approach for GIMP. More of a, “You give us some code. We’ll see if we like it” vibe. The disadvantages? Contributors have less control and sense of power if that’s what they want in open source. Some may value the greater openness used by the likes of Bitcoin. The advantages? GIMP’s development can be more focused and directed with a fewer number of people managing ideas of how things are run.

So which is preferable to contribute to? With my preliminary research, I wouldn’t be able to say. But it seems like preference at the end of the day. Personally, I’m liking Bitcoin’s way:)

Contributing to open source software packages