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 байт
                  
                  
                
Там ещё вопрос к тому, как ты замеряешь.
 adamfull
                          
                        
                      
                    
                    
                    
                    
                      Автор вопроса
                      
                      
                        
                          adamfull
                          
                        
                      
                    
                    
                    
                    
                      Автор вопроса
                    
                    
                  chrono::high_resolution_clock и 100000000 семплов
Возьми https://github.com/google/benchmark
 adamfull
                          
                        
                      
                    
                    
                    
                    
                      Автор вопроса
                      
                      
                        
                          adamfull
                          
                        
                      
                    
                    
                    
                    
                      Автор вопроса
                    
                    
                  Спасибо, завтра уже гляну
Ты похоже просто два скалярных произведения vec3 в симд положил и ждешь прироста. То есть вместо 5 операций, у тебя стало 2 раза переложить в память, потом 1 раз перемножить вектора, вынуть и сложить 3 раза. Все верно?
 adamfull
                          
                        
                      
                    
                    
                    
                    
                      Автор вопроса
                      
                      
                        
                          adamfull
                          
                        
                      
                    
                    
                    
                    
                      Автор вопроса
                    
                    
                  Не совсем понял по поводу того что два положил
 adamfull
                          
                        
                      
                    
                    
                    
                    
                      Автор вопроса
                      
                      
                        
                          adamfull
                          
                        
                      
                    
                    
                    
                    
                      Автор вопроса
                    
                    
                  1 раз положил, 1 раз перемножил, 8 раз сложил и два раза зашафлил. Скорее так
Смотри бинарь
У тебя a=1 всегда, его можно не считать. Так же коэффициенты 2 и 4 можно сократить в неравенстве, тоже не нужны в расчете. Скорее всего тормозит шафл, как будто быстрее скалярно поэлементно сложить. А так же возможно компилятор не смог переставить порядок вычислений и ему нужно явно поставить инструкции для 2-х скалярных умножений рядом: __m256 заюзать для двух векторных умножений, 64 битный проц же.
Обсуждают сегодня