Four Counters One Line

Four threads, each pinned to its own socket, run this. Each thread gets a distinct id in 0..3.

struct counter { long value; };
static struct counter counters[4];   /* 32 bytes total */

void *worker(void *arg) {
    int id = *(int *)arg;
    for (long i = 0; i < 500000000L; i++)
        counters[id].value++;
    return NULL;
}

One thread finishes in 1.6 s. Four threads take 18 s. No thread ever touches another thread's element. More than one of the following removes the slowdown. Which do?

A

Change value to _Atomic long and increment it atomically.

B

Allocate counters with malloc instead of making it a static array.

C

Pad struct counter to 64 bytes and align counters to a 64-byte boundary.

D

Accumulate into a local long inside worker and store it into counters[id].value once, after the loop.

E

Declare value as volatile long.