Wenn mit GCC kompiliert 5.2 mit -std=c99
, -O3
und -mavx2
, die folgende Codebeispiel Auto-vektorisiert (assembly here):Wie vektorisiert fortschreitende Schreibvorgänge mit GCC?
#include <stdint.h>
void test(uint32_t *restrict a,
uint32_t *restrict b) {
uint32_t *a_aligned = __builtin_assume_aligned(a, 32);
uint32_t *b_aligned = __builtin_assume_aligned(b, 32);
for (int i = 0; i < (1L << 10); i += 2) {
a_aligned[i] = 42 * b_aligned[i];
a_aligned[i+1] = 3 * a_aligned[i+1];
}
}
Aber die folgende Codebeispiel nicht automatisch vectorize (assembly here):
#include <stdint.h>
void test(uint32_t *restrict a,
uint32_t *restrict b) {
uint32_t *a_aligned = __builtin_assume_aligned(a, 32);
uint32_t *b_aligned = __builtin_assume_aligned(b, 32);
for (int i = 0; i < (1L << 10); i += 2) {
a_aligned[i] = 42 * b_aligned[i];
a_aligned[i+1] = a_aligned[i+1];
}
}
Der einzige Unterschied zwischen den Proben ist der Skalierungsfaktor a_aligned[i+1]
.
Dies war auch der Fall für GCC 4.8, 4.9 und 5.1. Durch Hinzufügen der volatile
zu a_aligned
Deklaration wird die automatische Vektorisierung vollständig verhindert. Das erste Beispiel läuft für uns konsistent schneller als das zweite, mit einer stärkeren Beschleunigung für kleinere Typen (z. B. uint8_t
anstelle von uint32_t
).
Gibt es eine Möglichkeit, das zweite Codebeispiel mit GCC zu vektorisieren?
Also der einzige Unterschied ist der Skalierungsfaktor (3 gegen nichts)? Versuchen Sie, 1 explizit als Skalierungsfaktor hinzuzufügen. Wenn das das Problem löst, ist das ein Compilerfehler. – Jeff
Oder versuchen Sie, die Anweisung 'a_aligned [i + 1] = a_aligned [i + 1]' zu kommentieren oder sie als 'a_aligned [i + 1] * = 1' umzuschreiben. Der Compiler weiß möglicherweise nicht, was er mit Ihrer No-Op-Selbstzuweisung machen soll, außer genau das zu tun, was Sie ihm gesagt haben. –
@Jeff Tatsächlich ist der einzige Unterschied der Skalierungsfaktor. Durch Hinzufügen einer expliziten 1 wird das zweite Codebeispiel nicht automatisch vektorisiert ([assembly here] (https://goo.gl/dnjSaQ)). –