Следует ли передавать или создавать типы данных SSE для каждой операции?

В настоящее время я пробую свои силы в создании собственной векторной математической библиотеки C++, и я заинтересован в ее оптимизации с помощью SSE. Для моих типов данных vec2 и vec3 я не могу хранить тип __m128 напрямую, так как они должны иметь ожидаемые размеры, но как насчет vec4? Предположим, мой тип vec4 выглядит примерно так (, игнорируя требование выравнивания по 16 -байтам для простоты обсуждения):

union vec4 {
  struct {float x, y, z, w;};
  __m128 sse;
}

vec4 operator+(const vec4& left, const vec4& right) {
  vec4 result;
  result.sse = _mm_add_ps(left.sse, right.sse);
  return result;
}

Это предлагаемый способ сделать это или есть какая-то веская причина, о которой я не могу думать? То есть, должен ли я сделать это вместо этого:

struct vec4 {
  float x, y, z, w;
};

vec4 operator+(const vec4& left, const vec4& right) {
  __m128 leftSSE = _mm_load_ps(reinterpret_cast<const float*>(&left));
  __m128 rightSSE = _mm_load_ps(reinterpret_cast<const float*>(&right));
  __m128 resultSSE = _mm_add_ps(leftSSE, rightSSE);
  vec4 result;
  _mm_store_ps(reinterpret_cast<float*>(&result), resultSSE);
  return result;
}

И пока мы на этом, как насчет моих теоретических типов vec2 и vec3? Было бы быстрее сначала преобразовать их в vec4, а затем использовать SIMD-инструкции или просто обрабатывать их скалярные элементы по отдельности?

5
задан Jo Bates 21 July 2012 в 22:38
поделиться