0
SSE를 사용하기 위해 일부 코드를 다시 작성하려고합니다. 그러나 어떤 이유로 SSE 버전이 원본과 다른 결과를 생성합니다 (예 : 1.47 등 대신 209.1 ..SSE 버전이 다른 결과
왜? 전체 기능은 here입니다.
struct vec_ps
{
__m128 value;
vec_ps(){}
vec_ps(float value) : value(_mm_set1_ps(value)) {}
vec_ps(__m128 value) : value(value) {}
vec_ps(const vec_ps& other) : value(other.value) {}
vec_ps& operator=(const vec_ps& other)
{
value = other.value;
return *this;
}
vec_ps& operator+=(const vec_ps& other)
{
value = _mm_add_ps(value, other.value);
return *this;
}
vec_ps& operator-=(const vec_ps& other)
{
value = _mm_sub_ps(value, other.value);
return *this;
}
vec_ps& operator*=(const vec_ps& other)
{
value = _mm_mul_ps(value, other.value);
return *this;
}
vec_ps& operator/=(const vec_ps& other)
{
value = _mm_div_ps(value, other.value);
return *this;
}
static vec_ps load(float* ptr)
{
return vec_ps(_mm_load_ps(ptr));
}
static void stream(float* ptr, const vec_ps& other)
{
_mm_stream_ps(ptr, other.value);
}
void stream(float* ptr)
{
_mm_stream_ps(ptr, value);
}
};
vec_ps operator+(const vec_ps& lhs, const vec_ps& rhs)
{
return vec_ps(lhs) += rhs;
}
vec_ps operator-(const vec_ps& lhs, const vec_ps& rhs)
{
return vec_ps(lhs) -= rhs;
}
vec_ps operator*(const vec_ps& lhs, const vec_ps& rhs)
{
return vec_ps(lhs) *= rhs;
}
vec_ps operator/(const vec_ps& lhs, const vec_ps& rhs)
{
return vec_ps(lhs) /= rhs;
}
void foo(/*...*/)
{
std::vector<float, tbb::cache_aligned_allocator<float>> ref_mu(w*h);
std::vector<float, tbb::cache_aligned_allocator<float>> cmp_mu(w*h);
std::vector<float, tbb::cache_aligned_allocator<float>> ref_sigma_sqd(w*h);
std::vector<float, tbb::cache_aligned_allocator<float>> cmp_sigma_sqd(w*h);
std::vector<float, tbb::cache_aligned_allocator<float>> sigma_both(w*h);
int size = w*h*sizeof(float);
/*...*/
float ssim_sum = 0.0;
float ssim_sum2 = 0.0;
vec_ps ssim_sum_ps(0.0f);
for(int n = 0; n < size/16; ++n)
{
auto ref_mu_ps = vec_ps::load(ref_mu.data() + n*4);
auto cmp_mu_ps = vec_ps::load(cmp_mu.data() + n*4);
auto sigma_both_ps = vec_ps::load(sigma_both.data() + n*4);
auto ref_sigma_sqd_ps = vec_ps::load(ref_sigma_sqd.data() + n*4);
auto cmp_sigma_sqd_ps = vec_ps::load(cmp_sigma_sqd.data() + n*4);
auto numerator = (2.0f * ref_mu_ps * cmp_mu_ps + C1) * (2.0f * sigma_both_ps + C2);
auto denominator = (ref_mu_ps*ref_mu_ps + cmp_mu_ps*cmp_mu_ps + C1) * (ref_sigma_sqd_ps + cmp_sigma_sqd_ps + C2);
ssim_sum_ps += numerator/denominator;
}
for(int n = 0; n < 4; ++n)
ssim_sum2 += ssim_sum_ps.value.m128_f32[n];
for (int y = 0; y < h; ++y)
{
int offset = y*w;
for (int x = 0; x < w; ++x, ++offset)
{
float numerator = (2.0f * ref_mu[offset] * cmp_mu[offset] + C1) * (2.0f * sigma_both[offset] + C2);
float denominator = (ref_mu[offset]*ref_mu[offset] + cmp_mu[offset]*cmp_mu[offset] + C1) * (ref_sigma_sqd[offset] + cmp_sigma_sqd[offset] + C2);
ssim_sum += numerator/denominator;
}
}
assert(ssim_sum2 == ssim_sum); // FAILS!
}
직접 디버깅 할 수 있으며 디버깅해야합니다. 디버거에서 실행하거나 printf 호출을 추가하여 중간 결과를 출력하십시오. 예상대로 작동하지 않는 단계를 분리 할 때 최소한의 테스트 사례를 작성하고 여기에서 질문하십시오. 그러나 "여기에 코드의 벽이있어 무엇이 잘못 됐는지를 알아 내라"는 좋은 질문이 아닙니다. –
@BenVoigt; Ofc, 당신 말이 맞아요. 그러나, 나는 그것을 알아낼 수없는 게시 전에 제안한 일을 alrdy했습니다. – ronag
그래서 어떤 코드 라인이 "잘못된"결과를 산출합니까? TBB 할당 자 등을 제거하고 단순화 할 수 있습니까? –