У меня есть код, который работает с значениями __m128
. Я использую x86-64 SSE intrinsics для этих значений, и я нахожу, что если значения не выравниваются в памяти, я получаю сбой. Это связано с моим компилятором (clang в этом случае), генерирующим только согласованные инструкции загрузки.Как дать команду компилятору генерировать неуравновешенные нагрузки для __m128
Могу ли я дать команду моему компилятору генерировать неравномерные нагрузки вместо этого, глобально или для определенных значений (возможно, с какой-либо аннотацией)?
Причина, по которой у меня есть несогласованные значения, заключается в том, что я пытаюсь сохранить память. У меня есть struct
примерно следующим образом:
#pragma pack(push, 4)
struct Foobar {
__m128 a;
__m128 b;
int c;
};
#pragma pack(pop)
Я затем создать массив этих структур. 2-й элемент в массиве начинается с 36 байт, который не кратен 16.
Я знаю, что я могу переключиться на структуру представления массивов или удалить прагму упаковки (за счет увеличения размера struct от 36 до 48 байт); но я также знаю, что неуправляемые нагрузки в наши дни не так дороги и хотели бы попробовать это в первую очередь.
Update, чтобы ответить на некоторые из приведенных ниже комментариев:
Мой реальный код был ближе к этому:
struct Vector4 {
__m128 data;
Vector4(__m128 v) : data(v) {}
};
struct Foobar {
Vector4 a;
Vector4 b;
int c;
}
Я тогда некоторые вспомогательные функции, такие как:
inline Vector4 add(const Vector4& a, const Vector4 &b) {
return Vector4(_mm_add_ps(a.data, b.data));
}
inline Vector4 subtract(const Vector4& a, const Vector4& b) {
return Vector4(_mm_sub_ps(a.data, b.data));
}
// etc..
Я использую эти утилиты часто в сочетании. Поддельный пример:
Foobar myArray[1000];
myArray[i+1].b = sub(add(myArray[i].a, myArray[i].b), myArray[i+1].a);
При взгляде на «Z Бозон» 'ы ответ на мой код эффективно изменен на:
struct Vector4 {
float data[4];
};
inline Vector4 add(const Vector4& a, const Vector4 &b) {
Vector4 result;
_mm_storeu_ps(result.data, _mm_add_ps(_mm_loadu_ps(a.data), _mm_loadu_ps(b.data)));
return result;
}
Моя проблема заключалась в том, когда функции полезности используются в комбинации, как указано выше, что сгенерированный код может иметь избыточные инструкции по загрузке/хранению. Оказывается, это не проблема. Я тестировал свой компилятор (clang), и он удалил их все. Я согласен с ответом Z Bozon.
Не используйте '__m128' в своей структуре. Используйте, например, 'float a [4]' и явно загружайте и сохраняйте файлы с '_mm_loadu_ps' и' _mm_storeu_ps'. –
Похоже, что OP не только использует явные интрижки, но и получает код SIMD, генерируемый clang из-за автоматической векторизации в некоторых случаях? –
@PaulR, если это так, то OP должен добавить эту информацию к своему вопросу. –