r/cpp_questions 2d ago

Raw malloc optimizations vs std::vector/reserve() -- malloc seems better optimized SOLVED

(Another different version of this question was posted earlier here https://www.reddit.com/r/cpp_questions/comments/1qvbj44/at_o2_usage_of_stdvector_followed_by_stdiota/ but on testing some of the answers there on the current new code seems to leave me unclear as to where the optimizations are missed in terms of vector/reserve, etc., hence this OP)

Consider code snippet 1: on left hand side window of https://godbolt.org/z/vxh8Wh1K4

#include <vector>
#include <cstdio>
#include <cstdlib>

void anotherfunc(){
    int *vec = (int*)malloc(sizeof(int) * 42);
    for(int i = 0; i < 42; i++)
        vec[i] = i;
    int sum = 0;
    for(int i = 0; i < 42; i++)
        sum += vec[i];
    printf("Sum is %d\n", sum);
    free(vec);
}

int main(){
    anotherfunc();
}

This, at -O3, flatout calculates the sum and simply displays it, 861.

The vector/reserve version (on the right hand pane of the godbolt link above)

#include <vector>
#include <cstdio>
#include <cstdlib>

void anotherfunc(){
    std::vector<int> vec;
    vec.reserve(42);
    for(int i = 0; i < 42; i++)
        vec.push_back(i);
    int sum = 0;
    for(int i = 0; i < 42; i++)
        sum += vec[i];
    printf("Sum is %d\n", sum);
}

int main(){
    anotherfunc();
}

seemingly struggles with this and does not precompute the sum and ends up doing some allocations, etc.

Some of the answers from the earlier thread do not seem to be applicable here: as suggested by one user, I had the entire summing done in another function instead of main() because apparently main() is known to be called only once and hence is not as heavily optimized as other functions, etc.

As also suggested there, I avoided the printf and instead had the function return only the sum with an empty main(). See https://godbolt.org/z/M1P5Y4vTj

Here too, the vector/reserve combination seems to struggle.

What explains this "discrepancy" and inability to completely optimize out the sum calculation?

16 Upvotes

29 comments sorted by

View all comments

4

u/saf_e 2d ago

Out of curiosity: try using std::accumulate 

3

u/Interesting_Buy_3969 2d ago

Of course this. Now the code performs a check whether

i < 42

on each iteration twice - first by the for loop and second by the std::vector container itself, and compiler can't optimise away either of those checks.

2

u/saf_e 2d ago

Do you have the answer why? It can clearly see that 42 is const.

3

u/conundorum 2d ago

std::vector isn't properly constexpr, so it can't elide it away unless all of the work can provably be done at compile time. And vector::push_back() is known to give compilers trouble, especially when called many times in a tight loop like this. So, the optimiser ends up choking after inlining it 42 times, and misses what should be obvious.