How can I get full CPU usage with C?

Today is our first class with C in college. After introducing the language, our lecturer said us to write some programs and we did that. She also asked me to try to write a program that uses 100% CPU. My initial thought was using a non-termination while loop, so I wrote this program.


int main()
{
    while (1){}
}

This only produced 50% of load on my dual core cpu. So I think that it is using only core. So I need a way to make it work on all the cores at the same time. How can I achieve this?

Run it in parallel, how to do that in C, no idea.

fork()!

Cas :slight_smile:

@princec
I don’t know what [icode]fork()[/icode] does. Can you explain that a bit? I now changed the code to


#include <stdio.h>

int main()
{
    int pid = fork();

    while (1){}
}

and gcc is saying that


localhost:Desktop sriharshachilakapati$ gcc fullCpu.c
fullCpu.c:5:15: warning: implicit declaration of function 'fork' is invalid in
      C99 [-Wimplicit-function-declaration]
    int pid = fork();
              ^
1 warning generated.

What does this mean?

Adding that [icode]fork()[/icode] two times worked, but it still prints that warning. What should I explain to my lecturer about that function? I’m now searching for it.

This may help to define the fork function


#include <sys/types.h>
#include <stdlib.h>
#include <unistd.h>

Mind you, don’t just fork, as that will spawn new child processes recursively, until the OS crashes.

Thanks princec for your help. It’s working fully and I found a documentation for the [icode]fork()[/icode] function here. I changed my final code to this.


#include <stdio.h>
#define NUM_CORES = 2

int main()
{
    for (int i=0; i<NUM_CORES-1; i++)
    {
        fork();
    }

    while (1){}
}

Thanks again princec.

when NUM_CORES > 2, this will spawn way too many processes. Remember that the forked processes will start to fork too.

Oh I see. How can I prevent it to fork on the childs?

By handling control flow appropriately, based on the returned value, like:


    for (int i=0; i<n; i++) {
        if(fork() == 0) { // is child process? then perform busy-loop
            while(1){}
        }
    }

This created exactly two processes in activity monitor.


#include <stdio.h>

int main()
{
    int ret = -1;
    int numCores = 2;

    if (ret != 0)
    {
        for (int i=0; i<numCores-1; i++)
        {
            ret = fork();
        }
    }

    while (1){}
}

Thanks princec and Riven.

try setting numCores to 8 then, and be surprised

Ghosh! It created 128 processes. I changed it to this and it creates exactly the same number of processes for each core.


#include <stdio.h>

int main()
{
    int numCores = 8;

    for (int i=0; i<numCores; i++)
    {
        if (fork() == 0)
        {
            while (1){}
        }
    }
}

Thanks again.

Your code doesn’t work for 1 core

Oops, a typo. Now it works perfectly.

I find that running threads equal to the number of cores does not necessarily mean you will get full CPU usage. The OS will try to favor a single core if possible (as it can be clocked higher) so if you spawn, say, three threads on an 8 thread CPU, you might find only one core in action. It’s all a bit murky. If you spawn enough threads, and that might mean a few more than eight in this case, then you will shoot up in a nonlinear fashion to full CPU usage.

At least that’s true with Java and using default thread priority - perhaps C has more luck.

Eh, it’s actually quite the opposite. If you even spawn 1 thread, it will be moved among all cores. Adding more threads will spread the load even better over all cores.

Not sure what you mean. If I have one thread on an i7, I get x performance, if I have 10 threads I get 6x performance (and flattens out at that point). However the increase is not linear and often you get no more than x performance, even at, say, 4 threads. The performance never goes lower than x, so I’m guessing that the threads are sometimes pushed onto a single core.

Contention and hyper threading muddy the waters, but you can be rest assured that the OS will not try to push more than 1 thread on 1 core exclusively. As said, it’s actually the opposite: 1 thread will hop between all cores.

Yes, I know the thread moves around between cores, but a single thread is never simultaneously on more than one core. Apparently if the cores are in any way busy (as they very likely are) windows is not too smart about what core to pick for a new thread.

In the i7 case, it only takes 4 threads to occupy all the (real) cores, and then apparently windows gets a bit random about where it allocates new threads.

EDIT: I’ve tried to find a reference for my initial assertion that the scheduler would favor a single core wrt turbo boost, but i can’t find one. Looks like I must have dreamed that one.