2

In the following code, I allocate two arrays of ints dynamically, and only initialize one of them.
Why is it that assigning a value to the initialized variable is faster than assigning it to the uninitialized one? (~0.4 nanoseconds vs ~4 ns, compiled with g++ 7.4.0 with the -O3 flag, and n = 10000)

#include <chrono>
#include <iostream>

#define NOW std::chrono::high_resolution_clock::now
#define DURATION_CAST(x)                                                       \
    std::chrono::duration_cast<std::chrono::nanoseconds>(x).count()

int main(int argc, char* argv[])
{
    int n = atoi(argv[1]);
    srand(time(nullptr));

    int* x = new int[n];
    int* y = new int[n];

    for (int i = 0; i < n; ++i)
    {
        x[i] = rand() / (RAND_MAX / 2);
    }

    auto t0 = NOW();
    for (int i = 0; i < n; ++i)
        x[i] = 1;

    auto t1 = NOW();
    for (int i = 0; i < n; ++i)
        y[i] = 1;

    auto t2 = NOW();
    double dt1 = DURATION_CAST(t1 - t0);
    double dt2 = DURATION_CAST(t2 - t1);

    std::cout << "Average time: " << dt1 / n << " ns" << std::endl;
    std::cout << "Average time: " << dt2 / n << " ns" << std::endl;

    delete[] x;
    delete[] y;

    return 0;
}

Here's a version with additional print statements in case the compiler optimizes away the important parts.

Kitegi
  • 262
  • 2
  • 7
  • I see uninitialised arrays in your code. Where is the initialised one? – Irelia May 24 '19 at 12:34
  • @Nina it's getting initialized by the `x[i] = rand() / (RAND_MAX / 2);` – Blaze May 24 '19 at 12:34
  • Most likely because `x` is already in the cache. Switch the loops around so you do `y` first and then compare the times. – NathanOliver May 24 '19 at 12:35
  • @NathanOliver Gives the same results. The loop assigning to y is still slower. – Kitegi May 24 '19 at 12:36
  • @Kitegi You answered at own question :) Initialized is faster because of uninitialized needs initiation :P – Raffallo May 24 '19 at 12:39
  • @Raffallo I could be wrong, but I'm assuming the memory allocation happens when the arrays are created. Why does modifying allocated memory take longer the first time? – Kitegi May 24 '19 at 12:40
  • I don't really trust your test - because it's a sample of 1; 4ns isn't very long; even in computing. Try doing the test ... a few million times (should still only take a couple of seconds). – UKMonkey May 24 '19 at 12:42
  • I assumed you meant initialise at compile time vs initialise at runtime. Compile time will be faster because the data is written to the variable at compile time... – Irelia May 24 '19 at 12:43
  • 4
    Oh, I know what's going on now. There should be a dupe and I'll try and find it but in the mean time what happens is the OS doesn't actually give you the memory you requested in `int* y = new int[n];` until you actually go to use it. So for `x` you use it already so the memory is allocated already. for `y` you don't so you have the time of the memory getting allocated in the `y` loop. – NathanOliver May 24 '19 at 12:43
  • @NathanOliver But the OS is required to give me contiguous memory, right? How can it do that without allocating it in one go? – Kitegi May 24 '19 at 12:44
  • @Kitegi It is reserved, but not actually allocated until you actually need it. – NathanOliver May 24 '19 at 12:45
  • @Kitegi It'll still be contiguous, it just doesn't happen until you try to access it. That's an OS "optimisation" of a sort, or rather just how virtual memory works.. – Lightness Races in Orbit May 24 '19 at 12:45

0 Answers0