我正在處理將-1.0到1.0範圍內的浮點取樣轉換爲帶符號16位的應用程序,以確保優化(SSE)例程的輸出準確無誤一組針對SSE版本運行非優化版本的測試,並比較它們的輸出。SSE向下取整
在我開始之前,我已確認SSE舍入模式設置爲最近。
在我的測試情況下,計算公式爲:
ratio = 65536/2
output = round(input * ratio)
在大多數情況下的結果是準確的,但在一個特定的輸入,我看到了的-0.8499908447265625
輸入失敗。
-0.8499908447265625 * (65536/2) = -27852.5
正常碼正確四捨五入這-27853
,但上交所代碼輪這-27852
。
這裏是使用上證所代碼:
void Float_S16(const float *in, int16_t *out, const unsigned int samples)
{
static float ratio = 65536.0f/2.0f;
static __m128 mul = _mm_set_ps1(ratio);
for(unsigned int i = 0; i < samples; i += 4, in += 4, out += 4)
{
__m128 xin;
__m128i con;
xin = _mm_load_ps(in);
xin = _mm_mul_ps(xin, mul);
con = _mm_cvtps_epi32(xin);
out[0] = _mm_extract_epi16(con, 0);
out[1] = _mm_extract_epi16(con, 2);
out[2] = _mm_extract_epi16(con, 4);
out[3] = _mm_extract_epi16(con, 6);
}
}
自我的要求含有實施例:
/* standard math */
float ratio = 65536.0f/2.0f;
float in [4] = {-1.0, -0.8499908447265625, 0.0, 1.0};
int16_t out[4];
for(int i = 0; i < 4; ++i)
out[i] = round(in[i] * ratio);
/* sse math */
static __m128 mul = _mm_set_ps1(ratio);
__m128 xin;
__m128i con;
xin = _mm_load_ps(in);
xin = _mm_mul_ps(xin, mul);
con = _mm_cvtps_epi32(xin);
int16_t outSSE[4];
outSSE[0] = _mm_extract_epi16(con, 0);
outSSE[1] = _mm_extract_epi16(con, 2);
outSSE[2] = _mm_extract_epi16(con, 4);
outSSE[3] = _mm_extract_epi16(con, 6);
printf("Standard = %d, SSE = %d\n", out[1], outSSE[1]);
您可以將其減少爲一個自包含的示例程序來演示問題嗎? –
在執行前後保存參數的值可能很有用。 – VermillionAzure
這是** all **浮點處理的默認行爲,而不僅僅是SSE。 [半捨棄或銀行四捨五入](https://en.wikipedia。org/wiki/Rounding#Round_half_to_even)是根據IEEE 754標準的默認舍入模式。原因在於,當應用於許多數字時,這將舍入誤差最小化,而舍入保證存在半點誤差。 –