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) \