Skip to main content
Asking for SIMD code to be written is off-topic
Link
200_success
  • 144.2k
  • 22
  • 188
  • 473

Fastest way to compute sum of Sum a list of string numbers

corrected tag -- this is C++11, not C
Link
Edward
  • 66.6k
  • 4
  • 118
  • 282
Source Link

Fastest way to compute sum of 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 <cstdint>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <unistd.h>
#include <limits.h>
#include <sys/stat.h>

#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, &sb );
    data = (char*)malloc(sb.st_size + 1 );
    size_t totalRead = 0UL;
    while (totalRead  < sb.st_size)
    {
        ssize_t bytesRead = read(STDIN_FILENO, data + totalRead, sb.st_size - totalRead);
        if ( bytesRead <= 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(&data);
    int32_t sum = 0;
    for (unsigned ii = 0; unlikely(ii < count); ii++ )
    {
        sum += fast_atoi(&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