Я работаю над улучшением кода интерполяции Эрмита с 16-битным целочисленным потоком с использованием SSE / SSE2 (или даже SSE3 / 4 / AVX ...)
Пока у меня все работает отлично, но мне интересно, смогу ли я оптимизировать его еще дальше. И еще мне интересно, смогу ли я быстрее загрузить 16-битные целочисленные данные.
Спасибо за любой совет.
Вот оригинальный код интерполяции Эрмита.
Hermite Interpolation
//
public static float InterpolateHermite4pt3oX(float x0, float x1, float x2, float x3, float t)
{
float c0 = x1;
float c1 = .5F * (x2 - x0);
float c2 = x0 - (2.5F * x1) + (2 * x2) - (.5F * x3);
float c3 = (.5F * (x3 - x0)) + (1.5F * (x1 - x2));
return (((((c3 * t) + c2) * t) + c1) * t) + c0;
}
Вот мой код SSE.
static __m128 S0, S1, S2, S3;
static __m128 dot5 = _mm_set1_ps(0.5f);
static __m128 TwoDot5 = _mm_set1_ps(2.5f);
static __m128 OneDot5 = _mm_set1_ps(1.5f);
static __m128 One = _mm_set1_ps(1.0f);
static __m128 Two = _mm_set1_ps(2.0f);
static __m128 mul16b = _mm_set1_ps(BITS_16_MULT);
#define HIC0 S1
#define HIC1 _mm_mul_ps(dot5, _mm_sub_ps(S2, S0))
#define HIC2 _mm_sub_ps(_mm_add_ps(_mm_sub_ps(S0, _mm_mul_ps(TwoDot5, S1)), _mm_mul_ps(Two, S2)), _mm_mul_ps(dot5, S3))
#define HIC3 _mm_add_ps(_mm_mul_ps(dot5, _mm_sub_ps(S3, S0)), _mm_mul_ps(OneDot5, _mm_sub_ps(S1, S2)))
#define HICRETURN _mm_add_ps(_mm_mul_ps(_mm_add_ps(_mm_mul_ps(_mm_add_ps(_mm_mul_ps(HIC3, fract), HIC2), fract), HIC1), fract), HIC0)
__m128 fract = _mm_set1_ps(fractPos);
_mm_store_ps(tempWave, HICRETURN);
S0 - S3 - образцы, Sample0 - Sample3. FractPos - это дробная позиция от одного образца к следующему.
А для чтения образцов я использую:
int16* xData = (int16*)sampleData16Bits.getData();
tempWave[0] = float(xData[newPosition]);
tempWave[1] = float(xData[newPosition + 1]);
tempWave[2] = float(xData[newPosition + 2]);
tempWave[3] = float(xData[newPosition + 3]);
S0 = _mm_mul_ps(_mm_load_ps(tempWave), mul16b);
S1 = _mm_shuffle_ps(S0, S0, 0x39);
S2 = _mm_shuffle_ps(S1, S1, 0x39);
S3 = _mm_shuffle_ps(S2, S2, 0x39);