Это как можно ближе к векторизации этого кода. Я не ожидаю, что это будет быстрее. Я просто пытался писать SIMD-код.
#include <stdint.h>
int64_t fun(int64_t N, int size, const int* p)
{
int64_t sum = 0;
int i;
for(i=1; i<size; i++) {
sum += (N/i)*p[i];
}
return sum;
}
typedef int64_t v2sl __attribute__ ((vector_size (2*sizeof(int64_t))));
int64_t fun_simd(int64_t N, int size, const int* p)
{
int64_t sum = 0;
int i;
v2sl v_2 = { 2, 2 };
v2sl v_N = { N, N };
v2sl v_i = { 1, 2 };
union { v2sl v; int64_t a[2]; } v_sum;
v_sum.a[0] = 0;
v_sum.a[1] = 0;
for(i=1; i<size-1; i+=2) {
v2sl v_p = { p[i], p[i+1] };
v_sum.v += (v_N / v_i) * v_p;
v_i += v_2;
}
sum = v_sum.a[0] + v_sum.a[1];
for(; i<size; i++) {
sum += (N/i)*p[i];
}
return sum;
}
typedef double v2df __attribute__ ((vector_size (2*sizeof(double))));
int64_t fun_simd_double(int64_t N, int size, const int* p)
{
int64_t sum = 0;
int i;
v2df v_2 = { 2, 2 };
v2df v_N = { N, N };
v2df v_i = { 1, 2 };
union { v2df v; double a[2]; } v_sum;
v_sum.a[0] = 0;
v_sum.a[1] = 0;
for(i=1; i<size-1; i+=2) {
v2df v_p = { p[i], p[i+1] };
v_sum.v += (v_N / v_i) * v_p;
v_i += v_2;
}
sum = v_sum.a[0] + v_sum.a[1];
for(; i<size; i++) {
sum += (N/i)*p[i];
}
return sum;
}
#include <stdio.h>
static const int test_array[] = {
1, 0, -1, 0, 1, 0, -1, 0, 1, 0, -1, 0, 1, 0, -1, 0,
1, 0, -1, 0, 1, 0, -1, 0, 1, 0, -1, 0, 1, 0, -1, 0,
1, 0, -1, 0, 1, 0, -1, 0, 1, 0, -1, 0, 1, 0, -1, 0,
1, 0, -1, 0, 1, 0, -1, 0, 1, 0, -1, 0, 1, 0, -1, 0,
1, 0, -1, 0, 1, 0, -1, 0, 1, 0, -1, 0, 1, 0, -1, 0,
1, 0, -1, 0, 1, 0, -1, 0, 1, 0, -1, 0, 1, 0, -1, 0,
1, 0, -1, 0, 1, 0, -1, 0, 1, 0, -1, 0, 1, 0, -1, 0,
1, 0, -1, 0, 1, 0, -1, 0, 1, 0, -1, 0, 1, 0, -1, 0,
1, 0, -1, 0, 1, 0, -1, 0, 1, 0, -1, 0, 1, 0, -1, 0,
1, 0, -1, 0, 1, 0, -1, 0, 1, 0, -1, 0, 1, 0, -1, 0,
1, 0, -1, 0, 1, 0, -1, 0, 1, 0, -1, 0, 1, 0, -1, 0,
1, 0, -1, 0, 1, 0, -1, 0, 1, 0, -1, 0, 1, 0, -1, 0,
1, 0, -1, 0, 1, 0, -1, 0, 1, 0, -1, 0, 1, 0, -1, 0,
1, 0, -1, 0, 1, 0, -1, 0, 1, 0, -1, 0, 1, 0, -1, 0,
1, 0, -1, 0, 1, 0, -1, 0, 1, 0, -1, 0, 1, 0, -1, 0,
1, 0, -1, 0, 1, 0, -1, 0, 1, 0, -1, 0, 1, 0, -1, 0,
1, 0, -1, 0, 1, 0, -1, 0, 1, 0, -1, 0, 1, 0, -1, 0,
1, 0, -1, 0, 1, 0, -1, 0, 1, 0, -1, 0, 1, 0, -1, 0,
1, 0, -1, 0, 1, 0, -1, 0, 1, 0, -1, 0, 1, 0, -1, 0,
1, 0, -1, 0, 1, 0, -1, 0, 1, 0, -1, 0, 1, 0, -1, 0,
1, 0, -1, 0, 1, 0, -1, 0, 1, 0, -1, 0, 1, 0, -1, 0
};
#define test_array_len (sizeof(test_array)/sizeof(int))
#define big_N (1024 * 1024 * 1024)
int main(int argc, char *argv[]) {
int64_t res1;
int64_t res2;
int64_t res3;
v2sl a = { 123, 456 };
v2sl b = { 100, 200 };
union { v2sl v; int64_t a[2]; } tmp;
a = a + b;
tmp.v = a;
printf("a = { %ld, %ld }\n", tmp.a[0], tmp.a[1]);
printf("test_array size = %zd\n", test_array_len);
res1 = fun(big_N, test_array_len, test_array);
printf("fun() = %ld\n", res1);
res2 = fun_simd(big_N, test_array_len, test_array);
printf("fun_simd() = %ld\n", res2);
res3 = fun_simd_double(big_N, test_array_len, test_array);
printf("fun_simd_double() = %ld\n", res3);
return 0;
}