Sum a list of string numbers I have a list of 32-bit signed numbers in range [-10e5, 10e5] in string form read from stdin, and I would like to compute and print their sum in the fastest way possible.

The bottleneck is in the fast_atoi function (checked using callgrind)

I thinking of two ways for improvement : cache misses seems to be an issue, and SIMD (ideally, only SSE and SSE2) instructions could come to help, however i don't really know how to use them...

The input is in this form (signed 32-bit integers between -10e5 and 10e5, separated by '\n') : 

4
10
5
3
1


And the program should output :

19


Right now, my code is :

#include &lt;cstdint&gt;
#include &lt;cstdlib&gt;
#include &lt;cstdio&gt;
#include &lt;cstring&gt;
#include &lt;unistd.h&gt;
#include &lt;limits.h&gt;
#include &lt;sys/stat.h&gt;

#define likely(x)      __builtin_expect(!!(x), 1)
#define unlikely(x)    __builtin_expect(!!(x), 0)

char* data alignas(16) = nullptr;

inline void read_data()
{
    struct stat sb;
    int rc = fstat( STDIN_FILENO, &amp;sb );
    data = (char*)malloc(sb.st_size + 1 );
    size_t totalRead = 0UL;
    while (totalRead  &lt; sb.st_size)
    {
        ssize_t bytesRead = read(STDIN_FILENO, data + totalRead, sb.st_size - totalRead);
        if ( bytesRead &lt;= 0 )
        {
            break;
        }
        totalRead += bytesRead;
    }
}

inline int fast_atoi(char ** str )
{
    int val = 0;
    char neg = 1;
    if (**str == '-')
    {
        neg = -1;
        (*str)++;
    }
    while(unlikely(**str != '\n'))
    {
        val = val*10 + (*(*str)++ - '0');
    }
    ++*str;
    return val*neg;
}
int32_t process()
{
    size_t count = fast_atoi(&amp;data);
    int32_t sum = 0;
    for (unsigned ii = 0; unlikely(ii &lt; count); ii++ )
    {
        sum += fast_atoi(&amp;data);
    }
    return sum;
}
inline void write_ans(int32_t sum)
{
    printf("%d", sum);
}
int main()
{
    read_data();
    int32_t val = process();
    write_ans(val);
}


Callgrind report for this code : https://pastebin.com/Pnd0FzZb
Assembly output : https://godbolt.org/g/Ng3sVM
I see a few things that may help you improve your code.

Add some error checking

Many of the calls used in the code, including fstat and malloc can fail.  It's generally better to check for and handle such errors instead of ignoring them.  Even though your main concern is performance, these calls are only made once and so will add almost nothing to the runtime.

Here's an alternative main showing how that might look:

int main() {
    struct stat sb;
    char *data;
    if (fstat(STDIN_FILENO, &amp;sb) != 0 || (data = (char *)mmap(0, sb.st_size, PROT_READ, MAP_SHARED, STDIN_FILENO, 0)) == nullptr) {
        perror("Error reading stdin");
        return 1;
    } 
    std::cout &lt;&lt; sum(data, sb.st_size) &lt;&lt; '\n';
}


Avoid the use of global variables

The data variable is used within read_data and the poorly named process().  It's generally better to explicitly pass variables your function will need or declare them within the appropriately smallest possible scope rather than using the vague implicit linkage of a global variable.  

Avoid premature optimization

On my machine, omitting the use of the unlikely macro and the alignas(16) made no difference in the resulting speed of the program.  Generally, I only resort to such things if there is a measurable effect and performance is more important than portability.  Perhaps you've already measured and made this determination and perhaps the results are different on your machine.

Consider an alternative algorithm

An alternative algorithm, which yields times very similar to the ones with your original, might be employed here.  In particular, we could process the file from the end to the beginning instead of the usual direction.  This allows us to efficiently convert each number, only adding the converted number when encountering a newline.  Note that this also essentially throws away the first number (which is the count of numbers to follow) which is the correct behavior in this case, since that number is not intended to be included in the sum.  Here's one version of the sum routine for that algorithm:

int sum(const char *test, std::size_t len) {
    int result{0};
    int n{0};
    int mult{1};
    // start from the back and add digits
    for (const char *ptr = test+len-1; ptr &gt;= test; --ptr) {
        switch(*ptr) {
            case '\n':
                result += n;
                n=0;
                mult=1;
                break;
            case '-':
                n = -n;
                break;
            case '0':
            case '1':
            case '2':
            case '3':
            case '4':
            case '5':
            case '6':
            case '7':
            case '8':
            case '9':
                n += mult * (*ptr - '0');
                mult *= 10;
                break;
            default:
                std::cerr &lt;&lt; "Malformed input\n";
                exit(1);
        }
    }
    return result;
}