Идея: поскольку | sin'x | < 1, можно считать его значения по таблице с равномерным шагом, равным требуемой точности результата.
Реализация:
diff -ruN src-org/sunset.cpp src-tabsin/sunset.cpp --- src-org/sunset.cpp 2007-09-16 12:04:44.000000000 +0400 +++ src-tabsin/sunset.cpp 2007-11-07 21:38:07.000000000 +0300 @@ -115,6 +115,33 @@ } } +#define SIN_TAB_SZ 16384 +#define PI2 (2*3.141592653589793f) +float g_sinTab[2*SIN_TAB_SZ+1]; + +void fillSinTab() +{ + for(int i=0;i<2*SIN_TAB_SZ+1;++i) + { + g_sinTab[i]=sinf((i-SIN_TAB_SZ)*PI2/SIN_TAB_SZ); + } +} + +inline float tab_sinf(float v) +{ + int idx=(((int)(v*(SIN_TAB_SZ/PI2))) % SIN_TAB_SZ)+SIN_TAB_SZ; + return g_sinTab[idx]; +} + +inline float lin_sinf(float v) +{ + float i=fmodf(v,PI2)*SIN_TAB_SZ/PI2+SIN_TAB_SZ; + size_t idx=i; + float d=i-idx; + + return g_sinTab[idx]*(1-d)+g_sinTab[idx+1]*d; +} + /*-----------------------------------------------------------*/ #define DECLARE_ALIGNED_PTR(type, pName) \ @@ -320,6 +347,7 @@ /*---------------------------------------------------------------------------*/ if(iCurFrame == 1) { + fillSinTab(); iWaveMeshSize = iWaveHarmNum * iAngleHarmNum; if(iAllocated == 1) @@ -730,30 +758,34 @@ !!!!!!!!!!!!!!!!! Water surface modelling !!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ + pFlTmp = flArgSin[currentthread].aptr; + flDerivX = 0.; + flDerivY = 0.; +#if 1 for(t = 0; t < NKMAX; t++) { - OT = flOmega[t] * flTime; + OT = flOmegaTime[t]; KX1 = flK[t] * flDecartX[i][j]; KY1 = flK[t] * flDecartY[i][j]; for(l = 0; l < iAngleHarmNum; l++) { iSinIndex1 = t * iAngleHarmNum + l; - flArgSin[currentthread].aptr[iSinIndex1] = OT - + pFlTmp[iSinIndex1] = OT - KX1 * flAzimuthCosFi[l] - KY1 * flAzimuthSinFi[l] + - flRandomPhase[t*iAngleHarmNum + l]; + flRandomPhase[iSinIndex1]; } /* end for l */ } /* end for t */ - pFlTmp = flArgSin[currentthread].aptr; - +// ippsSin_32f_A11(pFlTmp,pFlTmp,iWaveMeshSize); #pragma ivdep + #pragma vector for(t=0; t<iWaveMeshSize; t++) - pFlTmp[t] = (float)sinf(pFlTmp[t]); + { + pFlTmp[t] = (float)tab_sinf(pFlTmp[t]); + } /* initialize the values of derivation */ - flDerivX = 0.0f; - flDerivY = 0.0f; /* dot product to compute derivation */ for(t = 0; t < iWaveMeshSize; t++) @@ -761,6 +793,7 @@ flDerivX += pFlTmp[t] * flAmplitudeX[t]; flDerivY += pFlTmp[t] * flAmplitudeY[t]; } +#endif /* Near horizont area correction */ flDerivX *= P2;
Результат: gcc – медленно, icc – догоняем ippsSinf. Основной тормоз – смешанная арифметика, перевод плавающего числа в целое. Существенный минус – цикл не векторизуется :7