Table of Contents

Использование ICC

Установил icc в Fedora 7 (только компилятор). Пришлось дополнительно yum install compat-libstdc++-33.i386

Документация: /opt/intel/cc/10.0.023/doc/main_cls/whnjs.htm

man: man -M /opt/intel/cc/10.0.023/man icc

Векторизация

Включается ключом -x… или -ax… В примере – -xP. Перед этим робовал -axT, но выяснил, что автоопределение типа процессора работает странно. С -axT Core Duo T2300 работал по коду сопроцессора, а не по SSE.

В совокупности с ippsSin время 5.808/кадр.

Изменения в Makefile и циклах:

diff -ruN src-org/Makefile src-icc/Makefile
--- src-org/Makefile    2007-09-17 17:43:08.000000000 +0400
+++ src-icc/Makefile    2007-11-03 22:28:21.000000000 +0300
@@ -53,22 +53,23 @@

 OBJ = .o

-CC         = gcc
+CC         = icc
 CPLAT      =
 CPROC      =
 CINC       = -I$(SRC_DIR)
 CDEFS      =
 COBJ       = -c -o$(OBJ_DIR)/$@
-CDEFOPT    = -O2
+CDEFOPT    = -O3 -xP -fp-model fast -fp-speculation fast -fno-math-errno -g
 COPT       =
 CFLAGS     =
 CFLAGS_ALL = $(CFLAGS) $(CINC) $(CDEFS) $(CDEFOPT) $(CPROC) $(CPLAT)

 LD         = g++
-LDPLAT     =
-LDFLAGS    =
+LDPLAT     =
+LDFLAGS    = -L/opt/intel/cc/10.0.023/lib
 LDOUTOPT   = -o "$(OUT_DIR)/$(BENCHMARK)"
-LIBS       = -lm -lc
+LIBS       = -lm -lc -lirc -limf -lsvml -lippcore -lippvm -lipgo
+# -lompstub -lomp_db -lguide
 LIBS_ALL   = $(LIBS)

 endif
diff -ruN src-org/sunset.cpp src-icc/sunset.cpp
--- src-org/sunset.cpp  2007-09-16 12:04:44.000000000 +0400
+++ src-icc/sunset.cpp  2007-11-05 11:38:25.000000000 +0300
@@ -45,6 +45,7 @@
 #include <omp.h>
 #endif
 #include "sunset.h"
+#include <ippvm.h>

 #define MIN(x,y)    (((x) < (y)) ? (x) : (y))
 #define MAX(x,y)    (((x) < (y)) ? (y) : (x))
@@ -730,6 +731,9 @@
 !!!!!!!!!!!!!!!!! Water surface modelling !!!!!!!!!!!!!!!!!!!!!!!!
 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 */
+
+                pFlTmp = flArgSin[currentthread].aptr;
+
                 for(t = 0; t < NKMAX; t++)
                 {
                     OT  = flOmega[t] * flTime;
@@ -739,17 +743,16 @@
                     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;
-
-                #pragma ivdep
-                for(t=0; t<iWaveMeshSize; t++)
-                    pFlTmp[t] = (float)sinf(pFlTmp[t]);
+                ippsSin_32f_A11(pFlTmp,pFlTmp,iWaveMeshSize);
+                //#pragma ivdep
+                //for(t=0; t<iWaveMeshSize; t++)
+                //    pFlTmp[t] = (float)sinf(pFlTmp[t]);

                 /* initialize the values of derivation */
                 flDerivX = 0.0f;

Оптимизация по результатам профилирования (PGO)

В CDEFOPT добавить -prof-gen. Откомпилировать, запустить. Появится файл с результатами профилирования. Заменить -prof-gen на -prof-use. Откомпилировать, запустить.

Существенной разницы не заметил.

OpenMP

В коде интересная ловушка: #pragma omp parallel for ordered. Насколько я понял из спецификации OpenMP, ordered в цикле позволяет помещать внутри него секции ordered, которые будут выполняться всегда в одном и том же порядке. Однако, в нашем коде нет таких секций. Убрал ordered. Скорость возросла как и ожидалось, почти вдвое, при сохранении точности. Странно, что gcc слово ordered не смутило.

В совокупности с ippSin и векторизацией – 2.843/кадр.

diff -ruN src-org/sunset.cpp src-icc/sunset.cpp
--- src-org/sunset.cpp  2007-09-16 12:04:44.000000000 +0400
+++ src-icc/sunset.cpp  2007-11-05 13:44:08.000000000 +0300
@@ -656,7 +657,7 @@
         flOmegaTime[i] = flTime * flOmega[i];

 #if defined (_OPENMP)
-    #pragma omp parallel for ordered \
+    #pragma omp parallel for \
         private(k, i, l, t, iPointIndex, iColorIndex, j) \
         private(T2, FI2, CT2, ST2, chStatus0, flR) \
         private(CFI2, SFI2, flDeltaFi2, flDeltaT2, flSunPoint) \