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