From ba7a732d3179cfc6708938ffa28caddd3fb90c03 Mon Sep 17 00:00:00 2001 From: Armin Friedl Date: Thu, 23 Jun 2016 23:29:47 +0200 Subject: [PATCH] =?UTF-8?q?aufr=C3=A4umen?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- plot/plot.py | 6 +- roofline/report/inputs/kernels.tex | 19 +-- roofline/report/inputs/roofline.tex | 2 +- roofline/report/report.aux | 4 +- roofline/report/report.fdb_latexmk | 28 ++-- roofline/report/report.log | 24 ++-- roofline/report/report.pdf | Bin 328260 -> 328183 bytes roofline/report/report.tex | 2 +- roofline/src/Makefile | 84 ++++++----- roofline/src/aikern.c | 201 +++++++++----------------- roofline/src/aikern.h | 216 ++++++++++++++++++++++++++++ roofline/src/roofline | Bin 26432 -> 0 bytes roofline/src/roofline.c | 49 +++---- roofline/src/roofline_avx | Bin 26328 -> 0 bytes roofline/src/roofline_avxfma | Bin 14040 -> 0 bytes roofline/src/roofline_avxfmafast | Bin 18136 -> 0 bytes roofline/src/roofline_o3 | Bin 22232 -> 0 bytes roofline/src/roofline_o3avx | Bin 18136 -> 0 bytes 18 files changed, 397 insertions(+), 238 deletions(-) delete mode 100755 roofline/src/roofline delete mode 100755 roofline/src/roofline_avx delete mode 100755 roofline/src/roofline_avxfma delete mode 100755 roofline/src/roofline_avxfmafast delete mode 100755 roofline/src/roofline_o3 delete mode 100755 roofline/src/roofline_o3avx diff --git a/plot/plot.py b/plot/plot.py index 850ec95..14a5fd8 100644 --- a/plot/plot.py +++ b/plot/plot.py @@ -25,8 +25,10 @@ while i<=64: values = [] bandwidth = 10.6 peak = 86.4 +basepeak = 54.4 ymem = [] ypeak = [] +ybasepeak = [] for i in np.arange(0,64,0.1): if bandwidth*i < peak: @@ -47,10 +49,12 @@ while i<=64: ymem.append(None) i*=2 + + #plot data #data = pd.Series(data=values, name='Peak Memory Bandwidth', index=np.arange(0,64,0.1)) -data = {'Peak Memory Bandwidth': pd.Series(ymem, index=xlbl), 'Peak Floating-Point Performance': pd.Series(ypeak, index=xlbl)} +data = {'Peak Memory Bandwidth': pd.Series(ymem, index=xlbl), 'Peak Floating-Point Performance (Turbo)': pd.Series(ypeak, index=xlbl)} df = pd.DataFrame(data) ax = df.plot() diff --git a/roofline/report/inputs/kernels.tex b/roofline/report/inputs/kernels.tex index c69863b..deff509 100644 --- a/roofline/report/inputs/kernels.tex +++ b/roofline/report/inputs/kernels.tex @@ -4,9 +4,8 @@ However the effective operational intensity of a given kernel in a high-level la All kernels were compiled with \verb|gcc 5.3.1| and different options. The compilation was checked with \verb|objdump -d -M intel-mnemonics|. For a more elaborate analysis of the disassembly on the testers computer, please refer to the header file \verb|aikern.h| that should come with this report. Additionally \verb|Makefile| provides all informations about the used and tested compiler options. -Good results\footnote{all, including the special FMA kernels, use only expected memory access, doing everything else in registers} were achieved with \verb|-O2 -mavx -mfma|. But \verb|-O2 -maxv -mfma| is a tradeoff between the best possible results and obviously correct compiled code. In fact the assembly almost looks like handwritten. If even more optimization is wanted \verb|-O3| can be used. To fully utilize FMA with packed doubles \verb|-Ofast| or \verb|-Ofast -ffast-math| has to be used. Be aware that more optimization than \verb|-O2 -maxv -mfma| results in a very hard to understand disassembly. \verb|-ffast-math| can even introduce rounding errors. It is not completely obvious that the highly optimized compiled code still has the wanted operational intensity. \verb|-O0| never works out. +Good results\footnote{all, including the special FMA kernels, use only expected memory access, doing everything else in registers} were achieved with \verb|-O2 -mavx -mfma|. But \verb|-O2 -maxv -mfma| is a tradeoff between the best possible results and obviously correct compiled code. In fact the disassembly almost looks like handwritten. If even more optimization is wanted \verb|-O3| can be used. To fully utilize FMA with packed doubles \verb|-Ofast| or \verb|-Ofast -ffast-math| has to be used. Be aware that more optimization than \verb|-O2 -maxv -mfma| results in a very hard to understand disassembly. \verb|-ffast-math| can even introduce rounding errors or reduce the executed FLOPs. It is not completely obvious that the highly optimized compiled still has the wanted operational intensity. \verb|-O0| never works out. -\bigskip \bigskip \begin{footnotesize} \noindent\emph{Remark:} Contrary to popular believe the roofline model is built atop the notion of operational intensity\footnote{FLOPs against bytes written to DRAM} kernels. The differences to arithmetic intensities are outlined in~\textcite{williams2009}. Depending on the definition used these two terms are not necessarily interchangeable. The notion of operational intensity in the following sections might be what some would understand by the term arithmetic itensity. @@ -40,11 +39,13 @@ Two $\rfrac{1}{16}$ kernels have been implemented. The kernel in~\prettyref{lst: The simple kernel in~\prettyref{lst:1-16-simple} reads 8 bytes (a[i]) once for both operands of $*$ and writes 8 bytes (again to a[i]). This results in 16 byte operations. Only one FP instruction is executed, namely $*$. At \verb|-O2| the loop variable is held in a register. This results in an $\rfrac{1}{16}$ OI kernel. +\bigskip \begin{lstlisting}[caption={Simple $\rfrac{1}{16}$ OI kernel}, label=lst:1-16-simple] (*\textcolor{Orchid}{\#pragma omp parallel for}*) for(size_t i=0; i] Package hyperref Warning: Token not allowed in a PDF string (PDFDocEncoding): -(hyperref) removing `math shift' on input line 15. +(hyperref) removing `math shift' on input line 14. Package hyperref Warning: Token not allowed in a PDF string (PDFDocEncoding): -(hyperref) removing `\not' on input line 15. +(hyperref) removing `\not' on input line 14. Package hyperref Warning: Token not allowed in a PDF string (PDFDocEncoding): -(hyperref) removing `math shift' on input line 15. +(hyperref) removing `math shift' on input line 14. -[5] [6]) +[5] [6]) [7] Overfull \hbox (19.7725pt too wide) in paragraph at lines 116--116 \T1/cmtt/m/n/10.95 blob / e5aa9ca4a77623ff6f1c2d5daa7995565b944506 / stream . c # L286$[][] \T1/cmr/m/n/10.95 (-20) (vis-ited on 06/20/2016). [] -[7] + AED: lastpage setting LastPage [8] Package atveryend Info: Empty hook `BeforeClearDocument' on input line 117. @@ -1401,13 +1401,13 @@ Package logreq Info: Writing requests to 'report.run.xml'. Package atveryend Info: Empty hook `AtVeryVeryEnd' on input line 117. ) Here is how much of TeX's memory you used: - 21436 strings out of 493339 - 338721 string characters out of 6141383 - 878402 words of memory out of 5000000 + 21442 strings out of 493339 + 338775 string characters out of 6141383 + 879402 words of memory out of 5000000 24309 multiletter control sequences out of 15000+600000 - 29876 words of font info for 133 fonts, out of 8000000 for 9000 + 30053 words of font info for 136 fonts, out of 8000000 for 9000 953 hyphenation exceptions out of 8191 - 48i,8n,76p,1008b,1880s stack positions out of 5000i,500n,10000p,200000b,80000s + 48i,8n,76p,1001b,1880s stack positions out of 5000i,500n,10000p,200000b,80000s {/usr/share/texlive/texmf-dist/fonts/enc/dvips/cm-super/cm-super-ts1.enc}{/us r/share/texlive/texmf-dist/fonts/enc/dvips/cm-super/cm-super-t1.enc} -Output written on report.pdf (8 pages, 328260 bytes). +Output written on report.pdf (8 pages, 328183 bytes). PDF statistics: 353 PDF objects out of 1000 (max. 8388607) 278 compressed objects within 3 object streams diff --git a/roofline/report/report.pdf b/roofline/report/report.pdf index aba6179cf1d20f63f2cfa7107f7703271ad2e001..3548addf942efecd0ef71c67cd02c680ac13b3bf 100644 GIT binary patch delta 30301 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

?T2)x_!Zo*67E55jY?r@Q-aF*OIa#JZ5@7k*al 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�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 NZa7Lx2}Mb`{|Cp9Y&8G? delta 30280 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 diff --git a/roofline/report/report.tex b/roofline/report/report.tex index 7688648..1e4c767 100644 --- a/roofline/report/report.tex +++ b/roofline/report/report.tex @@ -89,7 +89,7 @@ \maketitle \begin{abstract} - A \emph{roofline model} for a multicore-processor is obtained by calcuating the theoretical peak performance of the processor and benchmarking the peak memory bandwith. Two artificial computational kernels with arithmetic intensities of $\frac{1}{16}$ GFLOPs/Byte and $8$ GFLOPs/Byte are devised. The performance of the two kernels is then compared to the theoretical calculations in the roofline model. + A \emph{roofline model} for a multicore-processor is obtained by calcuating the theoretical peak performance of the processor and benchmarking the peak memory bandwith. Two artificial computational kernels with operational intensities of $\frac{1}{16}$ GFLOPs/Byte and $8$ GFLOPs/Byte are devised. The performance of the two kernels is then compared to the theoretical calculations in the roofline model. \end{abstract} \tableofcontents diff --git a/roofline/src/Makefile b/roofline/src/Makefile index 8c2b285..adb4fb0 100644 --- a/roofline/src/Makefile +++ b/roofline/src/Makefile @@ -1,58 +1,66 @@ -all: roofline roofline_avx roofline_o3avx roofline_o3 roofline_avxfma roofline_avxfmafast +all: bin lib # Roofline Binary +bin: roofline roofline_o3 roofline_fma roofline_fma_o3 roofline_fma_fast_o3 roofline_fma_fast_fastmath_o3 + mkdir bin + mv $^ bin + roofline: roofline.c aikern.a gcc -Wall -Wextra -std=c99 -fopenmp $^ -o $@ -roofline_avx: roofline.c aikern_avx.a - gcc -Wall -Wextra -O3 -std=c99 -fopenmp $^ -o $@ - -roofline_o3avx: roofline.c aikern_o3avx.a - gcc -Wall -Wextra -O3 -std=c99 -fopenmp $^ -o $@ - roofline_o3: roofline.c aikern_o3.a - gcc -Wall -Wextra -O3 -std=c99 -fopenmp $^ -o $@ + gcc -Wall -Wextra -std=c99 -fopenmp $^ -o $@ -roofline_avxfma: roofline.c aikern_avxfma.a - gcc -Wall -Wextra -O3 -std=c99 -fopenmp $^ -o $@ +roofline_fma: roofline.c aikern_fma.a + gcc -Wall -Wextra -std=c99 -fopenmp $^ -o $@ + +roofline_fma_o3: roofline.c aikern_fma_o3.a + gcc -Wall -Wextra -std=c99 -fopenmp $^ -o $@ + +roofline_fma_fast_o3: roofline.c aikern_fma_fast_o3.a + gcc -Wall -Wextra -std=c99 -fopenmp $^ -o $@ + +roofline_fma_fast_fastmath_o3: roofline.c aikern_fma_fast_fastmath_o3.a + gcc -Wall -Wextra -std=c99 -fopenmp $^ -o $@ -roofline_avxfmafast: roofline.c aikern_avxfmafast.a - gcc -Wall -Wextra -O3 -std=c99 -fopenmp $^ -o $@ # Static Libraries -aikern.a: aikern.c aikern.h - gcc -c -o aikern.o aikern.c - ar rcs aikern.a aikern.o +lib: aikern.a aikern_o3.a aikern_fma.a aikern_fma_o3.a aikern_fma_fast_o3.a aikern_fma_fast_fastmath_o3.a + mkdir lib + mv $^ lib -aikern_avx.a: aikern.c aikern.h - gcc -mavx -c -o aikern_avx.o aikern.c - ar rcs aikern_avx.a aikern_avx.o +aikern.a: aikern.c aikern.h + gcc -Wall -Wextra -Wno-unused -fopenmp -c -o aikern.o $< + ar rcs aikern.a aikern.o + rm aikern.o aikern_o3.a: aikern.c aikern.h - gcc -O3 -c -o aikern_o3.o aikern.c - ar rcs aikern_o3.a aikern_o3.o + gcc -Wall -Wextra -Wno-unused -O3 -fopenmp -c -o aikern_o3.o $< + ar rcs $@ aikern_o3.o + rm aikern_o3.o -aikern_o3avx.a: aikern.c aikern.h - gcc -O3 -mavx -c -o aikern_o3avx.o aikern.c - ar rcs aikern_o3avx.a aikern_o3avx.o +aikern_fma.a: aikern.c aikern.h + gcc -Wall -Wextra -Wno-unused -O2 -mavx -mfma -fopenmp -c -o aikern_fma.o $< + ar rcs $@ aikern_fma.o + rm aikern_fma.o -# This is the only version that actually uses FMA -aikern_avxfma.a: aikern.c aikern.h - gcc -O2 -mavx -mfma -c -o aikern_avxfma.o aikern.c - ar rcs aikern_avxfma.a aikern_avxfma.o +aikern_fma_o3.a: aikern.c aikern.h + gcc -Wall -Wextra -Wno-unused -O3 -mavx -mfma -fopenmp -c -o aikern_fma_o3.o $< + ar rcs $@ aikern_fma_o3.o + rm aikern_fma_o3.o -aikern_avxfmafast.a: aikern.c aikern.h - gcc -O2 -mavx -mfma -Ofast -c -o aikern_avxfmafastmath.o aikern.c - ar rcs aikern_avxfmafast.a aikern_avxfmafastmath.o - -aikern_avxfmafastmath.a: aikern.c aikern.h - gcc -O2 -mavx -mfma -Ofast -ffast-math -c -o aikern_avxfmafastmath.o aikern.c - ar rcs aikern_avxfmafast.a aikern_avxfmafastmath.o +aikern_fma_fast_o3.a: aikern.c aikern.h + gcc -Wall -Wextra -Wno-unused -O3 -mavx -mfma -fopenmp -Ofast -c -o aikern_fma_fast_o3.o $< + ar rcs $@ aikern_fma_fast_o3.o + rm aikern_fma_fast_o3.o +aikern_fma_fast_fastmath_o3.a: aikern.c aikern.h + gcc -Wall -Wextra -Wno-unused -O3 -mavx -mfma -fopenmp -Ofast -ffast-math -c -o aikern_fma_fast_fastmath_o3.o $< + ar rcs $@ aikern_fma_fast_fastmath_o3.o + rm aikern_fma_fast_fastmath_o3.o +# Cleanup clean: - rm -f roofline roofline_avx roofline_o3avx roofline_o3 roofline_avxfma roofline_avxfmafast - rm -f *.o - rm -f *.a - rm -f *.so + rm -fR bin + rm -fR lib diff --git a/roofline/src/aikern.c b/roofline/src/aikern.c index 1ff84cb..72d53d3 100644 --- a/roofline/src/aikern.c +++ b/roofline/src/aikern.c @@ -1,88 +1,46 @@ # include +# include +# include +# include +# include +# include +# include + +# include "aikern.h" + +/** + * @brief terminate program on program error + * @param msg additional message to print + * @param ret exit value + */ +static void bail_out(char* fmt, ...); + +/** + * @brief microseconds since epoch + */ +static double pin_time(void); void kernel_1_16_simple(double* a, double* b, double* c, size_t size) { + double t = pin_time(); #pragma omp parallel for for(size_t i=0; i AI = 1/16 - */ a[i] = a[i] * a[i]; } } void kernel_1_16_fuseaware(double* a, double* b, double* c, size_t size) { - /* === Warning === - This is dangerous if FMA is not used/can't be used. Then there - are intermediary writes (and reads) to the stack. With FMA: - - vmovsd xmm0,QWORD PTR [rdi+rax*8] # 1 read - vmovsd xmm1,QWORD PTR [rdx+rax*8] # 1 read - vfmadd132sd xmm0,xmm1,QWORD PTR [rsi+rax*8] # 2 FLOPs + 1 read - vmovsd QWORD PTR [rdi+rax*8],xmm0 # 1 write - - Uses packed doubles with -Ofast. - */ - #pragma omp parallel for for(size_t i=0; i AI = 2/32 = 1/16 - */ a[i] = a[i] * b[i] + c[i]; } } -#define REP0(X) -#define REP1(X) X -#define REP2(X) REP1(X) REP1(X) -#define REP3(X) REP2(X) REP1(X) -#define REP4(X) REP3(X) REP1(X) -#define REP5(X) REP4(X) REP1(X) -#define REP6(X) REP5(X) REP1(X) -#define REP7(X) REP6(X) REP1(X) -#define REP8(X) REP7(X) REP1(X) -#define REP9(X) REP8(X) REP1(X) - -#define REP10(X) REP9(X) REP1(X) -#define REP20(X) REP10(X) REP10(X) -#define REP30(X) REP20(X) REP10(X) -#define REP40(X) REP30(X) REP10(X) -#define REP50(X) REP40(X) REP10(X) -#define REP60(X) REP50(X) REP10(X) - -#define REP100(X) REP50(X) REP50(X) - void kernel_8_1_simple(double* a, double* b, double* c, size_t size) { - /* === Warning === - Seems correct with -O3. Though -O3 does some loop unrolling. - - With -O0 this is dangerous, intermediary values stored on stack - who knows if they survive in cache -> unpredictable. - - With AVX and -O2 (not necessarily FMA) best results - (obviously correct, only register shuffling). With FMA: - - vmovsd xmm1,QWORD PTR [rdi] # 1 read - vmulsd xmm0,xmm1,xmm1 # 1 FLOP+register shuffling - vmulsd xmm0,xmm0,xmm1 # 127x 1 FLOP+register shuffling - # [...] - vmovsd QWORD PTR [rdi-0x8],xmm0 # 1 write - */ - #pragma omp parallel for for(size_t i=0; i AI = 128/16 = 8 - */ a[i] = REP100(a[i]*) REP20(a[i]*) REP8(a[i]*) @@ -92,88 +50,30 @@ void kernel_8_1_simple(double* a, double* b, double* c, size_t size) void kernel_8_1_fuseaware(double* a, double* b, double* c, size_t size) { - /* - With FMA (and -O2): - - vmovsd xmm0,QWORD PTR [rdi] # 1 read - vfmadd132sd xmm0,xmm0,xmm0 # 64 x 2 FLOPs+register shuffling - vmovsd QWORD PTR [rdi-0x8],xmm0 # 1 write - - Uses packed doubles with -Ofast. - */ - #pragma omp parallel for for(size_t i=0; i AI = 8 - */ REP60(a[i] = a[i] * a[i] + a[i];) REP4(a[i] = a[i] * a[i] + a[i];) } } -/* === FAILED KERNELS === */ - -/* - These are theoretically correct kernels but all of them yield - dangerous results with gcc 5.3.1 (checked the assembly). -*/ - void kernel_1_16_simple_dangerous(double* a, double* b, double* c, size_t size) { - /* === Problem === - As soon as volatile is used gcc uses the stack for tmp. - Even if "register" is in place. Resulting in one additional write per loop. - Omitting volatile results in optimizing away the whole loop - (checked at -O2, which is necessary for FMA to eventually step in). - Maybe the value stays in cache, maybe not. It does not live a register. - - Even with -O3: - movsd xmm0,QWORD PTR [rdi+rax*8] # 1 read - mulsd xmm0,QWORD PTR [rsi+rax*8] # 1 read (+ write to xmm0, not counted) - # [...] # instructions for loop - movsd QWORD PTR [rsp-0x8],xmm0 # malicious write - - Without volatile (-O3): - repz ret # that's it - */ - - - // volatile to prevent compiler from optimizing this away - // register to advise compiler to put this in register - double tmp = 0.1; + register volatile double tmp = 0.1; #pragma omp parallel for for(size_t i=0; i AI = 1/16 - */ tmp = a[i] * b[i]; } } void kernel_8_1_simple_dangerous(double* a, double* b, double* c, size_t size) { - /* === Problem == - Same as for kernel_1_16_simple_dangerous - */ - - // volatile to prevent compiler from optimizing this away - // register to advise compiler to put this in register - volatile register double tmp = 0.1; + register volatile double tmp = 0.1; #pragma omp parallel for for(size_t i=0; i AI = 8 - */ tmp = a[i] * a[i] * a[i] * a[i] * a[i] * a[i] * a[i] * a[i]; } @@ -183,18 +83,55 @@ void kernel_1_8_vo_dangerous(double* a, double* b, double* c, size_t size) { /* This is the 1/8 AI kernel from the lecture - === Problem == - Same as for kernel_1_16_simple_dangerous - - Without volatile the loop is optimized away completely. - With volatile tmp is written to the stack in every loop - (-O3). tmp could be cached or not. This might depend on - how large the array is and how the cpu work internally - -> unpredictable. */ - volatile double tmp=0.0; + register volatile double tmp=0.0; + for(size_t i=0; i 0) + (void)fprintf(stderr, "%s: %s \n", prog_name, msgbuf); + + } + + if(errno != 0) + (void)fprintf(stderr, "%s: %s\n", prog_name, strerror(errno)); + + exit(EXIT_FAILURE); } diff --git a/roofline/src/aikern.h b/roofline/src/aikern.h index 92193a1..b0a6ff8 100644 --- a/roofline/src/aikern.h +++ b/roofline/src/aikern.h @@ -1,8 +1,224 @@ +#ifndef AIKERN_H +#define AIKERN_H + +/** + * @brief A simple 1/16 operational intensity kernel + * @param a An array with double values of size param size + * @param b An array with double values of size param size + * @param c An array with double values of size param size + * @param size Size of the three param arrays + * + * === Warning === + * Don't use with -O0: Stores everything on stack + * + * === Description === + * Uses a simple floating point operation: a[i] = a[i] * a[i]; + * + * Runs in a parallelized for loop. + * + * === Analysis === + * COMM: 1 read (8 byte), 1 write = 16 bytes + * COMP: 1 FLOP + * --------- + * OI: 1/16 + * + * === Optimization === + * Nothing special + * + */ void kernel_1_16_simple(double* a, double* b, double* c, size_t size); + + + +/** + * @brief A 1/16 operational intensity kernel utilizing FMA + * @param a An array with double values of size param size + * @param b An array with double values of size param size + * @param c An array with double values of size param size + * @param size Size of the three param arrays + * + * === Warning === + * This is dangerous if FMA is not used/can't be used. Then there + * are intermediary writes (and reads) to the stack. + * + * === Description === + * Uses a triad function: a[i] = a[i] * b[i] + c[i]; in order + * to utilize the FMA unit. + * + * Runs in a parallelized for loop. + * + * === Analysis === + * With gcc -O2 -mavx -mfma FMA compiles to: + * vmovsd xmm0,QWORD PTR [rdi+rax*8] # 1 read (8 byte) + * vmovsd xmm1,QWORD PTR [rdx+rax*8] # 1 read + * vfmadd132sd xmm0,xmm1,QWORD PTR [rsi+rax*8] # 2 FLOPs + 1 read + * vmovsd QWORD PTR [rdi+rax*8],xmm0 # 1 write + * -------- + * 1/16 OI + * + * === Optimization === + * For packed doubles compile with -Ofast + * + */ void kernel_1_16_fuseaware(double* a, double* b, double* c, size_t size); + + + +/** + * @brief A simple 8/1 operational intensity kernel + * @param a An array with double values of size param size + * @param b An array with double values of size param size + * @param c An array with double values of size param size + * @param size Size of the three param arrays + * + * === Warning === + * Don't use with -O0: Stores everything on stack + * + * === Description === + * Uses a simple floating point operation: a[i] = a[i] * a[i] * ...* a[i]; + * + * Runs in a parallelized for loop. + * + * === Analysis === + * With AVX and -O2 (not necessarily FMA) best results (obviously correct + * easy to read disassembly). + * + * With gcc -O2 -mavx compiles to: + * vmovsd xmm1,QWORD PTR [rdi] # 1 read + * vmulsd xmm0,xmm1,xmm1 # 1 FLOP+register shuffling + * vmulsd xmm0,xmm0,xmm1 # 127x 1 FLOP+register shuffling + * # [...] + * vmovsd QWORD PTR [rdi-0x8],xmm0 # 1 write + * -------- + * 128/16 = 8/1 OI + * + * === Optimization === + * Nothing special + */ void kernel_8_1_simple(double* a, double* b, double* c, size_t size); + +/** + * @brief A 8/1 operational intensity kernel utilizing FMA + * @param a An array with double values of size param size + * @param b An array with double values of size param size + * @param c An array with double values of size param size + * @param size Size of the three param arrays + * + * === Warning === + * This is dangerous if FMA is not used/can't be used. Then there + * are intermediary writes (and reads) to the stack. + * + * === Description === + * Uses multiple triad function: a[i] = a[i] * a[i] + a[i]; in order + * to utilize the FMA unit. + * + * Runs in a parallelized for loop. + * + * === Analysis === + * With gcc -O2 -mavx -mfma FMA compiles to: + * vmovsd xmm0,QWORD PTR [rdi] # 1 read + * vfmadd132sd xmm0,xmm0,xmm0 # 64 x 2 FLOPs+register shuffling + * vmovsd QWORD PTR [rdi-0x8],xmm0 # 1 write + * -------- + * 128/16 = 8/1 OI + * + * === Optimization === + * For packed doubles compile with -Ofast + * + */ void kernel_8_1_fuseaware(double* a, double* b, double* c, size_t size); + +/******************************************** + * Kernels which potentially compile to * + * different operational intensities than * + * specified * + ********************************************/ + +/** + * @brief A 1/16 operational intensity which might compile to a flawed oi kernel + * @param a An array with double values of size param size + * @param b An array with double values of size param size + * @param c An array with double values of size param size + * @param size Size of the three param arrays + * + * === Problem === + * As soon as volatile is used gcc uses the stack for tmp. + * Even if "register" is in place. Resulting in one additional write per loop. + * Omitting volatile results in optimizing away the whole loop + * (checked at -O2, which is necessary for FMA to eventually step in). + * Maybe the value stays in cache, maybe not. It does not live a register. + * + * Even with -O3: + * movsd xmm0,QWORD PTR [rdi+rax*8] # 1 read + * mulsd xmm0,QWORD PTR [rsi+rax*8] # 1 read (+ write to xmm0, not counted) + * # [...] # instructions for loop + * movsd QWORD PTR [rsp-0x8],xmm0 # malicious write + * + * Without volatile (-O3): + * repz ret # that's it + */ void kernel_1_16_simple_dangerous(double* a, double* b, double* c, size_t size); + +/** + * @brief A 8/1 operational intensity which might compile to a flawed oi kernel + * @param a An array with double values of size param size + * @param b An array with double values of size param size + * @param c An array with double values of size param size + * @param size Size of the three param arrays + * + * === Problem == + * Same as for kernel_1_16_simple_dangerous + */ void kernel_8_1_simple_dangerous(double* a, double* b, double* c, size_t size); + +/** + * @brief A 1/8 operational intensity which might compile to a flawed oi kernel + * @param a An array with double values of size param size + * @param b An array with double values of size param size + * @param c An array with double values of size param size + * @param size Size of the three param arrays + * + * === Problem == + * Same as for kernel_1_16_simple_dangerous + * + * Without volatile the loop is optimized away completely. + * With volatile tmp is written to the stack in every loop + * (-O3). tmp could be cached or not. This might depend on + * how large the array is and how the cpu work internally + * -> unpredictable. + */ void kernel_1_8_vo_dangerous(double* a, double* b, double* c, size_t size); + + +/**************************************** + * Helper macros for repeating things * + ****************************************/ + +#define REP0(X) +#define REP1(X) X +#define REP2(X) REP1(X) REP1(X) +#define REP3(X) REP2(X) REP1(X) +#define REP4(X) REP3(X) REP1(X) +#define REP5(X) REP4(X) REP1(X) +#define REP6(X) REP5(X) REP1(X) +#define REP7(X) REP6(X) REP1(X) +#define REP8(X) REP7(X) REP1(X) +#define REP9(X) REP8(X) REP1(X) + +#define REP10(X) REP9(X) REP1(X) +#define REP20(X) REP10(X) REP10(X) +#define REP30(X) REP20(X) REP10(X) +#define REP40(X) REP30(X) REP10(X) +#define REP50(X) REP40(X) REP10(X) +#define REP60(X) REP50(X) REP10(X) + +#define REP100(X) REP50(X) REP50(X) + +#ifdef ENDEBUG +#define DEBUG(...) do { fprintf(stderr, __VA_ARGS__); fprintf(stderr, "\n"); } while(0) +#else +#define DEBUG(...) +#endif + +#endif /* AIKERN_H */ diff --git a/roofline/src/roofline b/roofline/src/roofline deleted file mode 100755 index e16bf7a12e9a08b4cae6489eab217af0ce63ce00..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 26432 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 Ue@N`)zvx!eo_=I&O?LnP1Ga?0CIA2c diff --git a/roofline/src/roofline.c b/roofline/src/roofline.c index 8fe4922..77539c4 100644 --- a/roofline/src/roofline.c +++ b/roofline/src/roofline.c @@ -57,7 +57,7 @@ static int get_int(char* oparg); /** * @brief microseconds since epoch */ -static double mysecond(void); +static double pin_time(void); /** * @brief a simple test kernel with ai of 1/16 @@ -103,10 +103,8 @@ int main(int argc, char* argv[]) { size_t size = get_size(size_arg); int runs = get_int(runs_arg); - printf("Will run with array sizes of %zu\n", size); + printf("Will run with array sizes of %zu elements\n", size); printf("Will calculate min, max, avg for %d runs\n", runs); - - /* Make this volatile so that nothing is optimized away here */ double* a = malloc(sizeof(double)*(size)); double* b = malloc(sizeof(double)*(size)); double* c = malloc(sizeof(double)*(size)); @@ -114,60 +112,53 @@ int main(int argc, char* argv[]) { if(a==NULL || b==NULL || c == NULL) bail_out("One of the mallocs failed\n. a = %p, b=%p, c=%p", a, b, c); - printf("Allocated 3 arrays\n"); - - printf("Filling arrays with dummy values\n"); + printf("Allocated 3 arrays (3*%.2f MB = %.2f GB)\n", (sizeof(double)*(size)/1024.0/1024.0), (sizeof(double)*(size)*3/1024.0/1024.0/1024)); + printf("Filling arrays with dummy values. This will also warm the cache\n"); - /* #pragma omp parallel for + #pragma omp parallel for for (size_t j=0; j}# z-<>xjKgm-6PP=E%uEyu-&i&@jojZ5t&HKOpe2Z_j-DYDl+1Uz4+@T7UL*_4I8+6VJ ztbxs9D*F(d$7TR2#isHSqGnFgNugTOG9l*xEy31cH-QGb$}^H)W5P^QX(3T+Zz`!G zYtoHPCMzjp3J0hj**ek2SUUPqJ&;*YlR79~E$9^BipC zYAU~f{oF6^tNE-ye(93x|JeRn2VU+yKxJ2AljFupDL0#2L-+@OguJJZp{RmuJDS%HrT zT<#~60zZ)>&oG~RBLjmpgFQ@d?QGKn!Dz6zKV}4@oo%Z^k#Mlnzd00Sy52hw3F|S# zA2oEH>9=gr*9o~*A%83ujG5K*R$jBVtwSI5NByBtFvQTF-WxRZaC|^F`l3O9AeO;Q zo{Gq{L6arx>R>@I8VyJEP^8;$^hd%Z&`m}4EV#AbV39$iKOA6#aU;fJM%0LeLJZ9S zW?N$6!DxTj=wSmeA<|8<{%9}6(Ay~MxjWi#1WDNF9|%Tz0{(5RM^u0&h(w}jp4t-* z81VOp8Sm9HSVq0`fUfbiHm%Z^)-J8R0sf|))`7ng{wt}u{}WF8dZ{Rr%dZW!FyxHZ zkveQ+ANeSTu#_zaNSNv-zJ#qNAtW3A{tcAM6m0RU`)5%L?UwSdi*gWAZqJlYuI(b2 zul2Ke&is+{hmJY4=Ex-H58+oy5LC`X!fBn7sanjpnE-@IyhyR&vhP%|z=F%UOL(0H zw;l%@EV%VJpjvQhTPDqd%YBB*IxILGm`NKfczFh8tjmI5X2JU`xYeJ77QDhDztw^} zE%*)#PGc+6{T94Rf}r~>_!SoXparL6k4)Oo>t))W(sQd7rtKavN>l%e5^d<|vLmKM z`i7TLl&*ONzs_q_7@j1cA0?g+kK>H0`0qPeJ$~Ji{}+Mv_ac5LrauC2*D>k%T=Z&ex7(UwG)+xCez0Jp~n^Q9rtzrrfhXX|w%xB7FSPAGXN-9+JV_n%C4P~52W?}( zw8W8nzmtLAOuZ!GqxU|fEk}!=cRuh{=

My@Z-%%5dEZm3c-|QHUnq7~WuV0dPK8 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 diff --git a/roofline/src/roofline_avxfmafast b/roofline/src/roofline_avxfmafast deleted file mode 100755 index 54782c3813f25c3245af40e87772e4df5c4b1aaf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 18136 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 EKW4TP%>V!Z diff --git a/roofline/src/roofline_o3avx b/roofline/src/roofline_o3avx deleted file mode 100755 index e339598a1fe1be2db4309719fb97bbdd36188707..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 18136 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