Как помочь gcc векторизовать код C
У меня есть следующий C-код. Первая часть просто читает в матрице комплексных чисел из стандартного в матрицу под названиемM
, Интересная часть - вторая часть.
#include <stdio.h>
#include <complex.h>
#include <stdlib.h>
#include <assert.h>
#include <math.h>
int main() {
int n, m, c, d;
float re, im;
scanf("%d %d", &n, &m);
assert(n==m);
complex float M[n][n];
for(c=0; c<n; c++) {
for(d=0; d<n; d++) {
scanf("%f%fi", &re, &im);
M[c][d] = re + im * I;
}
}
for(c=0; c<n; c++) {
for(d=0; d<n; d++) {
printf("%.2f%+.2fi ", creal(M[c][d]), cimag(M[c][d]));
}
printf("\n");
}
/*
Example:input
2 3
1+2i 2+3i 74-4i
3+4i 4+5i -7-8i
*/
/* Part 2. M is now an n by n matrix of complex numbers */
int s=1, i, j;
int *f = malloc(n * sizeof *f);
complex float *delta = malloc(n * sizeof *delta);
complex float *v = malloc(n * sizeof *v);
complex float p = 1, prod;
for (i = 0; i < n; i++) {
v[i] = 0;
for (j = 0; j <n; j++) {
v[i] += M[j][i];
}
p *= v[i];
f[i] = i;
delta[i] = 1;
}
j = 0;
while (j < n-1) {
prod = 1.;
for (i = 0; i < n; i++) {
v[i] -= 2.*delta[j]*M[j][i];
prod *= v[i];
}
delta[j] = -delta[j];
s = -s;
p += s*prod;
f[0] = 0;
f[j] = f[j+1];
f[j+1] = j+1;
j = f[0];
}
free(delta);
free(f);
free(v);
printf("%f + i%f\n", creal(p/pow(2.,(n-1))), cimag(p/pow(2.,(n-1))));
return 0;
}
Я собираю сgcc -fopt-info-vec-all -O3 -ffast-math -march=bdver2 permanent-in-c.c -lm
, Это объясняет мне, почему почти ни один из циклов не векторизован.
Самая важная часть производительности - строки 47--50, которые:
for (i = 0; i < n; i++) {
v[i] -= 2.*delta[j]*M[j][i];
prod *= v[i];
}
GCC говорит мне:
permanent-in-c.c:47:7: note: reduction used in loop.
permanent-in-c.c:47:7: note: Unknown def-use cycle pattern.
permanent-in-c.c:47:7: note: reduction used in loop.
permanent-in-c.c:47:7: note: Unknown def-use cycle pattern.
permanent-in-c.c:47:7: note: Unsupported pattern.
permanent-in-c.c:47:7: note: not vectorized: unsupported use in stmt.
permanent-in-c.c:47:7: note: unexpected pattern.
[...]
permanent-in-c.c:48:26: note: SLP: step doesn't divide the vector-size.
permanent-in-c.c:48:26: note: Unknown alignment for access: IMAGPART_EXPR <*M.4_40[j_202]{lb: 0 sz: pretmp_291 * 4}[i_200]>
permanent-in-c.c:48:26: note: SLP: step doesn't divide the vector-size.
permanent-in-c.c:48:26: note: Unknown alignment for access: REALPART_EXPR <*M.4_40[j_202]{lb: 0 sz: pretmp_291 * 4}[i_200]>
[...]
permanent-in-c.c:48:26: note: Build SLP failed: unrolling required in basic block SLP
permanent-in-c.c:48:26: note: Failed to SLP the basic block.
permanent-in-c.c:48:26: note: not vectorized: failed to find SLP opportunities in basic block.
Как я могу исправить проблемы, которые мешают этой части векторизации?
Любопытно, что эта часть векторизована, но я не уверен, почему:
for (j = 0; j <n; j++) {
v[i] += M[j][i];
Полный вывод gcc -fopt-info-vec-all -O3 -ffast-math -march = bdver2 перманент-в-c.c -lm находится вhttps://bpaste.net/show/18ebc3d66a53.