0
votes

I'm currently writing a contrived producer/consumer program that uses a bounded buffer and a number of worker threads to multiply matrices (for the sake of exposition). While trying to assure that the concurrency of my program is optimal I'm observing some unusual behavior. Namely, when executing the program I am only able to achieve up to 100% CPU usage (observed in top), despite having 6 cores. Using shift-i to view the relative percentage changes the upper bound to ~%16.7 and I can clearly see when viewing the usage of different cores by pressing 1 that either only one core is fully maxed out or the load of one core is distributed amongst all six.

No matter what stress tests I run (I tried the stress program and a simple stress test that created multiple threads that spun) I cannot get a single process to use more than 100% (or ~%16.7 relative to all available cores) CPU, so I presume the parallelism is bound to a single core. This behavior is observed on an Ubuntu LTS 20.10 running within VirtualBox on a Mac host with a 2.3 GHz 8-Core Intel Core i9 processor. Is there some way I must enable multi-core parallelism in VirtualBox or is this perhaps just an idiosyncrasy of the setup?

For reference here is the simple stress test I used


void *prod_worker(void *arg) {
    while (1) {
        printf("...");
    }
}

int main (int argc, char * argv[])
{
  printf("pid: %lun\n", getpid());
  getc(stdin);
  int numw = atoi(argv[1]);

  pthread_t *prod_threads = malloc(sizeof(pthread_t) * numw);

  for (int i = 0; i < numw; i++) { 
    pthread_t prod;
    int rcp; 
    rcp = pthread_create(&prod, NULL, prod_worker, NULL);
    if (rcp == THREAD_CREATE_SUCCESS) { 
      prod_threads[i] = prod;
    } else {
      printf("Failed to create producer and consumer thread #%d...\n", i);
      printf("Error codes: prod = %d\n", rcp);
      printf("Retrying...\n");
      i--;
    }
  }

  for (int i = 0; i < numw; i++) {
    pthread_join(prod_threads[i], NULL);
  }
  return 0;
}

1

1 Answers

0
votes

printf is thread safe, which typically means there is a mutex of some kind on the stdout stream, such that only one thread can print at a time. Thus even though all your threads are "running", at any given time, all but one of them is likely to be waiting to take ownership of the stream, thus doing nothing useful and using no CPU.

You might want to instead try a test where the threads do some computation, instead of just I/O.