size_t _Size>
static inline vector_impl<_Ty, 2ull> ray_sphere_intersect(const vector_impl<_Ty, _Size>& r0, const vector_impl<_Ty, _Size>& rd, const vector_impl<_Ty, _Size>& s0, const _Ty sr)
{
vector_impl<_Ty, 2ull> res{};
_Ty a = length2(rd);
vector_impl<_Ty, _Size> s0_r0 = r0 - s0;
_Ty b = static_cast<_Ty>(2) * dot(rd, s0_r0);
_Ty c = length2(s0_r0) - (sr * sr);
if (b * b - static_cast<_Ty>(4) * a * c < static_cast<_Ty>(0))
{
res[0] = res[1] = -1.f;
return res;
}
res[0] = (-b - sqrt((b * b) - static_cast<_Ty>(4) * a * c)) / (static_cast<_Ty>(2) * a);
res[1] = (-b + sqrt((b * b) - static_cast<_Ty>(4) * a * c)) / (static_cast<_Ty>(2) * a);
return res;
}
И есть её такая же на sse2
inline __m128 _dot_product_sse2(const __m128& _lhs, const __m128& _rhs)
{
auto t0 = _mm_mul_ps(_lhs, _rhs);
auto t1 = _mm_shuffle_ps(t0, t0, _MM_SHUFFLE(2, 3, 0, 1));
t0 = _mm_add_ps(t0, t1);
t1 = _mm_shuffle_ps(t0, t0, _MM_SHUFFLE(0, 1, 2, 3));
return _mm_add_ps(t0, t1);
}
inline void _sphere_intersect_vec128(const float(&_r0)[3ull], const float(&_rd)[3ull], const float(&_s0)[3ull], const float _sr, float(&_res)[2ull])
{
using namespace sse;
__m128 vr0 = _load_fvec128(_r0);
__m128 vrd = _load_fvec128(_rd);
__m128 vs0 = _load_fvec128(_s0);
float a = _mm_cvtss_f32(_dot_product_sse2(vrd, vrd));
__m128 vs0_r0 = _mm_sub_ps(vr0, vs0);
float b = 2.f * _mm_cvtss_f32(_dot_product_sse2(vrd, vs0_r0));
float c = _mm_cvtss_f32(_dot_product_sse2(vs0_r0, vs0_r0)) - (_sr * _sr);
float discriminant = (b * b) - (4.f * a * c);
// Check discriminant is greather then zero
if (discriminant < 0.f)
{
_res[0] = _res[1] = -1.f;
return;
}
discriminant = sqrtf(discriminant);
float a2 = 2.f * a;
_res[0] = (-b - discriminant) / a2;
_res[1] = (-b + discriminant) / a2;
}
Компилирую msvc 2019, оптимизация O2. И у меня выходит, что код без использования sse2 быстрее в 10 раз. Подскажите почему такое может быть? Данные выровнены по 16 байт
Там ещё вопрос к тому, как ты замеряешь.
chrono::high_resolution_clock и 100000000 семплов
Возьми https://github.com/google/benchmark
Спасибо, завтра уже гляну
Ты похоже просто два скалярных произведения vec3 в симд положил и ждешь прироста. То есть вместо 5 операций, у тебя стало 2 раза переложить в память, потом 1 раз перемножить вектора, вынуть и сложить 3 раза. Все верно?
Не совсем понял по поводу того что два положил
1 раз положил, 1 раз перемножил, 8 раз сложил и два раза зашафлил. Скорее так
Смотри бинарь
У тебя a=1 всегда, его можно не считать. Так же коэффициенты 2 и 4 можно сократить в неравенстве, тоже не нужны в расчете. Скорее всего тормозит шафл, как будто быстрее скалярно поэлементно сложить. А так же возможно компилятор не смог переставить порядок вычислений и ему нужно явно поставить инструкции для 2-х скалярных умножений рядом: __m256 заюзать для двух векторных умножений, 64 битный проц же.
Обсуждают сегодня