ilp.tex 41 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363
  1. % vim: set foldmethod=marker foldmarker=<<<,>>>:
  2. \section{Instruction level optimization}
  3. % https://www.youtube.com/watch?v=BP6NxVxDQIs
  4. %<<< How code executes on a computer
  5. \begingroup
  6. \setbeamertemplate{background canvas}{%
  7. \begin{tikzpicture}[remember picture,overlay]
  8. \only<3>{
  9. \draw[line width=20pt,red!60!black]
  10. (11,-2) -- (15,-8);
  11. \draw[line width=20pt,red!60!black]
  12. (15,-2) -- (11,-8);
  13. }
  14. \end{tikzpicture}}
  15. \begin{frame}[fragile] \frametitle{How code executes on a computer}{}
  16. \begin{columns}
  17. \column{0.4\textwidth}
  18. \begin{overprint}
  19. \onslide<1->%<<<
  20. \begin{minted}[
  21. frame=lines,
  22. fontsize=\footnotesize,
  23. linenos,
  24. gobble=8,
  25. mathescape
  26. ]{C++}
  27. void laplace(double* u, double* x,
  28. double* y, double* f,
  29. long Ns, long Nt) {
  30. for (long t = 0; t < Nt; t++) {
  31. for (long s = 0; s < Ns; s++) {
  32. double rx, ry, rz;
  33. rx = x[s*3]-y[t*3];
  34. ry = x[s*3+1]-y[t*3+1];
  35. rz = x[s*3+2]-y[t*3+2];
  36. double r2 = rx*rx+ry*ry+rz*rz;
  37. if (r2 > 0) {
  38. double rinv = 1/sqrt(r2);
  39. u[t] += f[s] * rinv;
  40. }
  41. }
  42. }
  43. }
  44. \end{minted}
  45. %>>>
  46. \end{overprint}
  47. \column{0.25\textwidth}
  48. \center
  49. \resizebox{0.99\textwidth}{!}{\begin{tikzpicture} %<<<
  50. \draw[draw=black,ultra thick] (0,0) rectangle (4,4.2);
  51. \node at (2,3.8) {\Large CPU};
  52. \draw[draw=black,ultra thick] (0.25,0.125) rectangle (3.75,1.125);
  53. \node at (2,0.625) {\Large Cache};
  54. \draw[draw=black,ultra thick] (0.25,1.25) rectangle (3.75,2.25);
  55. \node at (2,1.75) {\Large Control Unit};
  56. \draw[draw=black,ultra thick] (0.25,2.375) rectangle (3.75,3.375);
  57. \node at (2,2.875) {\Large ALU};
  58. \draw[latex-latex, ultra thick] (1,0) -- (1,-1);
  59. \draw[latex-latex, ultra thick] (2,0) -- (2,-1);
  60. \draw[latex-latex, ultra thick] (3,0) -- (3,-1);
  61. \draw[draw=black,ultra thick] (0,-2.2) rectangle (4,-1);
  62. \node at (2,-1.6) {\Large RAM};
  63. \end{tikzpicture}} %>>>
  64. \column{0.31\textwidth}
  65. \begin{itemize}
  66. \setlength\itemsep{0.75em}
  67. \item code executes line-by-line
  68. \item sequentially and in order
  69. \item one scalar operation at a time
  70. \item one operation per clock cycle
  71. \end{itemize}
  72. \only<2>{}
  73. \end{columns}
  74. % Programming language and hardware abstraction go hand-in-hand
  75. % most languages don't make it easy to specify when it is safe to vectorize (aliasing)
  76. % lies! forget that!
  77. % you have been lied to!
  78. % that is not how code executes on a computer at all
  79. % instructions can execute in any order -- but you are guaranteed that the net effect is the same as sequential
  80. % execution
  81. \end{frame}
  82. \endgroup
  83. %>>>
  84. \begin{frame} \frametitle{Core microarchitecture}{} %<<<
  85. \begin{columns}[t]
  86. \column{0.55\textwidth}
  87. \resizebox{0.99\textwidth}{!}{\begin{tikzpicture}
  88. \only<1>{
  89. %\write18{wget -O figs/skylake-arch.svg https://en.wikichip.org/w/images/e/ee/skylake_server_block_diagram.svg}
  90. %\write18{convert figs/skylake-arch.svg figs/skylake-arch.png}
  91. \node at (0,0) {\includegraphics[width=0.9\textwidth]{figs/skylake-arch}};
  92. }
  93. \only<2>{
  94. \node[opacity=0] at (0,-1) {\includegraphics[width=0.9\textwidth]{figs/skylake-arch}};
  95. \node at (0,0) {\includegraphics[width=0.99\textwidth]{figs/skylake_scheduler}};
  96. \node at (0,-3) {\small Skylake micro-architecture (source: wikichip.org)};
  97. }
  98. \end{tikzpicture}}
  99. \column{0.45\textwidth}
  100. \begin{itemize}
  101. \setlength\itemsep{0.85em}
  102. \item {Branch prediction and speculative execution}
  103. \item {Out-of-order execution}
  104. \only<2>{
  105. \item {Superscalar execution:} \\
  106. \quad 2-FP, 2-reads, 1-write
  107. \item {Vector instructions}
  108. \item {Pipelining:} `assembly line' \\
  109. \quad latency and throughput
  110. }
  111. %Instruction pipelining where the execution of multiple instructions can be partially overlapped.
  112. %Superscalar execution, VLIW, and the closely related explicitly parallel instruction computing concepts, in which
  113. %multiple execution units are used to execute multiple instructions in parallel.
  114. %Out-of-order execution where instructions execute in any order that does not violate data dependencies. Note that
  115. %this technique is independent of both pipelining and superscalar execution. Current implementations of out-of-order
  116. %execution dynamically (i.e., while the program is executing and without any help from the compiler) extract ILP from
  117. %ordinary programs. An alternative is to extract this parallelism at compile time and somehow convey this information
  118. %to the hardware. Due to the complexity of scaling the out-of-order execution technique, the industry has re-examined
  119. %instruction sets which explicitly encode multiple independent operations per instruction.
  120. %Register renaming which refers to a technique used to avoid unnecessary serialization of program operations imposed
  121. %by the reuse of registers by those operations, used to enable out-of-order execution.
  122. %Speculative execution which allows the execution of complete instructions or parts of instructions before being
  123. %certain whether this execution should take place. A commonly used form of speculative execution is control flow
  124. %speculation where instructions past a control flow instruction (e.g., a branch) are executed before the target of
  125. %the control flow instruction is determined. Several other forms of speculative execution have been proposed and are
  126. %in use including speculative execution driven by value prediction, memory dependence prediction and cache latency
  127. %prediction.
  128. %Branch prediction which is used to avoid stalling for control dependencies to be resolved. Branch prediction is used
  129. %with speculative execution.
  130. \end{itemize}
  131. \end{columns}
  132. % CPU core complexity: https://www.youtube.com/watch?v=eICYHA-eyXM&t=555s
  133. % out-of-order, vector, branch-prediction
  134. \end{frame}
  135. %>>>
  136. \begin{frame} \frametitle{Instruction level parallelism}{} %<<<
  137. \center
  138. \includegraphics[width=0.8\textwidth]{figs/intel-core-gflops}
  139. {\footnotesize Source: John McCalpin - Memory bandwidth and system balance in HPC systems, 2016}
  140. \end{frame}
  141. %>>>
  142. \begin{frame}[fragile] \frametitle{Instruction latency and throughput}{} %<<<
  143. \begin{columns}[t]
  144. \column{0.45\textwidth}
  145. \footnotesize
  146. \begin{overprint}
  147. \onslide<1>%<<<
  148. \begin{minted}[
  149. frame=lines,
  150. fontsize=\footnotesize,
  151. linenos,
  152. gobble=8,
  153. mathescape
  154. ]{C++}
  155. #include <iostream>
  156. #include <omp.h>
  157. int main(int argc, char** argv) {
  158. double x = 3.141, one = 1.0;
  159. double T = -omp_get_wtime();
  160. for (long i = 0; i < 1000000000L; i++) {
  161. x = one + x;
  162. }
  163. T += omp_get_wtime();
  164. std::cout<<"T = "<< T <<'\n';
  165. std::cout<<"cycles/iter = "<< 3.3*T <<'\n';
  166. return 0;
  167. }
  168. \end{minted}
  169. %>>>
  170. \onslide<2-3>%<<<
  171. \begin{minted}[
  172. frame=lines,
  173. fontsize=\footnotesize,
  174. linenos,
  175. gobble=8,
  176. mathescape
  177. ]{C++}
  178. #include <iostream>
  179. #include <omp.h>
  180. int main(int argc, char** argv) {
  181. double x = 3.141, one = 1.0;
  182. double T = -omp_get_wtime();
  183. for (long i = 0; i < 1000000000L; i++) {
  184. x = one + x;
  185. }
  186. T += omp_get_wtime();
  187. std::cout<<"T = "<< T <<'\n';
  188. std::cout<<"cycles/iter = "<< 3.3*T <<'\n';
  189. std::cout<<x<<'\n';
  190. return 0;
  191. }
  192. \end{minted}
  193. %>>>
  194. \onslide<4-5>%<<<
  195. \begin{minted}[
  196. frame=lines,
  197. fontsize=\footnotesize,
  198. linenos,
  199. gobble=10,
  200. mathescape
  201. ]{C++}
  202. double x[32], one = 1;
  203. // ... initialize x
  204. double T = -omp_get_wtime();
  205. for (long i = 0; i < 1000000000L; i++) {
  206. x[0] = one + x[0];
  207. x[1] = one + x[1];
  208. x[2] = one + x[2];
  209. x[3] = one + x[3];
  210. ...
  211. x[31] = one + x[31];
  212. }
  213. T += omp_get_wtime();
  214. std::cout<<"T = "<< T <<'\n';
  215. std::cout<<"cycles/iter = "<< 3.3*T <<'\n';
  216. \end{minted}
  217. %>>>
  218. \end{overprint}
  219. \column{0.1\textwidth}
  220. \column{0.45\textwidth}
  221. \begin{overprint}
  222. \onslide<1-2>%<<<
  223. \begin{minted}[gobble=8,fontsize=\footnotesize]{text}
  224. $ g++ -O3 -march=native -fopenmp test.cpp
  225. $ ./a.out
  226. T = 0
  227. cycles/iter = 0
  228. \end{minted}
  229. %>>>
  230. \onslide<3-4>%<<<
  231. \begin{minted}[gobble=8,fontsize=\footnotesize]{text}
  232. $ g++ -O3 -march=native -fopenmp test.cpp
  233. $ ./a.out
  234. T = 0
  235. cycles/iter = 0
  236. $ g++ -O3 -march=native -fopenmp test.cpp
  237. $ ./a.out
  238. T = 1.22387
  239. cycles/iter = 4.03876
  240. \end{minted}
  241. %>>>
  242. \onslide<5-5>%<<<
  243. \begin{minted}[gobble=8,fontsize=\footnotesize]{text}
  244. $ g++ -O3 -march=native -fopenmp test.cpp
  245. $ ./a.out
  246. T = 0
  247. cycles/iter = 0
  248. $ g++ -O3 -march=native -fopenmp test.cpp
  249. $ ./a.out
  250. T = 1.22387
  251. cycles/iter = 4.03876
  252. $ g++ -O3 -march=native -fopenmp test.cpp
  253. $ ./a.out
  254. T = 1.22366
  255. cycles/iter = 4.03809
  256. \end{minted}
  257. \textcolor{red}{\qquad 8 adds/cycle!}
  258. %>>>
  259. \end{overprint}
  260. \end{columns}
  261. \end{frame}
  262. %>>>
  263. \begin{frame}[t] \frametitle{SIMD vector instructions}{} %<<<
  264. \begin{columns}[t]
  265. \column{0.7\textwidth}
  266. \only<1>{
  267. \begin{itemize}
  268. \setlength\itemsep{1em}
  269. \item Think in vectors instead of scalars (float, double)
  270. \item Re-organize computations as vector operations
  271. \begin{itemize}
  272. \item Struct-of-arrays (SOA) \\
  273. $\{x_1,y_1,z_1, ~~x_2,y_2,z_2, \cdots, ~~x_n,y_n,z_n\}$
  274. \item Array-of-struct (AOS) \\
  275. $\{x_1,\cdots, x_n, ~~y_1,\cdots, y_n, ~~z_1,\cdots, z_n\}$
  276. \end{itemize}
  277. \item Tell the compiler it is safe to use SIMD instructions
  278. \begin{itemize}
  279. \item most languages don't make it easy to specify when it is safe to vectorize (aliasing)
  280. \end{itemize}
  281. \end{itemize}
  282. }
  283. \only<2>{
  284. \begin{itemize}
  285. \setlength\itemsep{1em}
  286. \item {Auto vectorization:} \textcolor{red}{unreliable!}
  287. \begin{itemize}
  288. \item Compiler specific hints:\\
  289. {-fopt-info-vec-optimized} \\
  290. {\color{blue} \_\_builtin\_assume\_aligned(a, 32)} \\
  291. {\color{magenta} \#pragma ivdep}
  292. \item OpenMP 4.0: {\color{magenta} \#pragma omp simd}
  293. \end{itemize}
  294. \item {Assembly:} \textcolor{red}{too hard!}
  295. \item {Vector intrinsics:} \textcolor{red}{works but messy!}
  296. \begin{itemize}
  297. \item {\_mm512\_add\_pd(\_\_m512d, \_\_m512d)}
  298. \item {\_mm512\_mul\_pd(\_\_m512d, \_\_m512d)}
  299. \end{itemize}
  300. \item {C++ vector libraries:} \textcolor{green}{intuitive and clean}
  301. %\begin{itemize}
  302. % \item Vector objects, overloaded operators (+, -, *, $||$, \&\& etc)
  303. %\end{itemize}
  304. \end{itemize}
  305. }
  306. \only<3>{
  307. \begin{itemize}
  308. \setlength\itemsep{1em}
  309. \item {C++ vector libraries:} \textcolor{green}{intuitive and clean}
  310. \begin{itemize}
  311. \setlength\itemsep{1em}
  312. \item Vector objects, overloaded operators (+, -, *, $||$, \&\& etc)
  313. \item Vector Class Library - Agner Fog\\
  314. \url{https://github.com/vectorclass/version2}
  315. \item SLEEF Vectorized Math Library \\
  316. \item SCTL (\url{https://github.com/dmalhotra/SCTL})
  317. \item Similar proposals for future C++ standard library \\
  318. {\scriptsize \url{https://en.cppreference.com/w/cpp/experimental/simd}}
  319. \end{itemize}
  320. \end{itemize}
  321. }
  322. \column{0,3\textwidth}
  323. \center
  324. \begin{tikzpicture}%<<<
  325. \node at (0,0.5) {\scriptsize SSE};
  326. \node at (0,0.2) {\scriptsize 128-bit};
  327. \draw[fill=c2] (-0.7,-0.0) rectangle (-0.5,-0.2);
  328. \draw[fill=c2] (-0.7,-0.2) rectangle (-0.5,-0.4);
  329. \node at (-0.27,-0.2) {\scriptsize =};
  330. \draw[fill=c2] (0,-0.0) rectangle (0.2,-0.2);
  331. \draw[fill=c2] (0,-0.2) rectangle (0.2,-0.4);
  332. \node at (0.42,-0.2) {\scriptsize $+$};
  333. \draw[fill=c2] (0.7,-0.0) rectangle (0.9,-0.2);
  334. \draw[fill=c2] (0.7,-0.2) rectangle (0.9,-0.4);
  335. \draw[draw=none] (0.7,-1.4) rectangle (0.9,-1.6);
  336. \end{tikzpicture}%>>>
  337. \hspace{1.5em}
  338. \begin{tikzpicture}%<<<
  339. \node at (0,0.5) {\scriptsize AVX};
  340. \node at (0,0.2) {\scriptsize 256-bit};
  341. \draw[fill=c3] (-0.7,-0.0) rectangle (-0.5,-0.2);
  342. \draw[fill=c3] (-0.7,-0.2) rectangle (-0.5,-0.4);
  343. \draw[fill=c3] (-0.7,-0.4) rectangle (-0.5,-0.6);
  344. \draw[fill=c3] (-0.7,-0.6) rectangle (-0.5,-0.8);
  345. \node at (-0.27,-0.4) {\scriptsize =};
  346. \draw[fill=c3] (0,-0.0) rectangle (0.2,-0.2);
  347. \draw[fill=c3] (0,-0.2) rectangle (0.2,-0.4);
  348. \draw[fill=c3] (0,-0.4) rectangle (0.2,-0.6);
  349. \draw[fill=c3] (0,-0.6) rectangle (0.2,-0.8);
  350. \node at (0.42,-0.4) {\scriptsize $+$};
  351. \draw[fill=c3] (0.7,-0.0) rectangle (0.9,-0.2);
  352. \draw[fill=c3] (0.7,-0.2) rectangle (0.9,-0.4);
  353. \draw[fill=c3] (0.7,-0.4) rectangle (0.9,-0.6);
  354. \draw[fill=c3] (0.7,-0.6) rectangle (0.9,-0.8);
  355. \draw[draw=none] (0.7,-1.4) rectangle (0.9,-1.6);
  356. \end{tikzpicture}%>>>
  357. \begin{tikzpicture}%<<<
  358. \node at (0,0.5) {\scriptsize AVX512};
  359. \node at (0,0.2) {\scriptsize 512-bit};
  360. \draw[fill=c4] (-0.7,-0.0) rectangle (-0.5,-0.2);
  361. \draw[fill=c4] (-0.7,-0.2) rectangle (-0.5,-0.4);
  362. \draw[fill=c4] (-0.7,-0.4) rectangle (-0.5,-0.6);
  363. \draw[fill=c4] (-0.7,-0.6) rectangle (-0.5,-0.8);
  364. \draw[fill=c4] (-0.7,-0.8) rectangle (-0.5,-1.0);
  365. \draw[fill=c4] (-0.7,-1.0) rectangle (-0.5,-1.2);
  366. \draw[fill=c4] (-0.7,-1.2) rectangle (-0.5,-1.4);
  367. \draw[fill=c4] (-0.7,-1.4) rectangle (-0.5,-1.6);
  368. \node at (-0.27,-0.8) {\scriptsize =};
  369. \draw[fill=c4] (0,-0.0) rectangle (0.2,-0.2);
  370. \draw[fill=c4] (0,-0.2) rectangle (0.2,-0.4);
  371. \draw[fill=c4] (0,-0.4) rectangle (0.2,-0.6);
  372. \draw[fill=c4] (0,-0.6) rectangle (0.2,-0.8);
  373. \draw[fill=c4] (0,-0.8) rectangle (0.2,-1.0);
  374. \draw[fill=c4] (0,-1.0) rectangle (0.2,-1.2);
  375. \draw[fill=c4] (0,-1.2) rectangle (0.2,-1.4);
  376. \draw[fill=c4] (0,-1.4) rectangle (0.2,-1.6);
  377. \node at (0.42,-0.8) {\scriptsize $+$};
  378. \draw[fill=c4] (0.7,-0.0) rectangle (0.9,-0.2);
  379. \draw[fill=c4] (0.7,-0.2) rectangle (0.9,-0.4);
  380. \draw[fill=c4] (0.7,-0.4) rectangle (0.9,-0.6);
  381. \draw[fill=c4] (0.7,-0.6) rectangle (0.9,-0.8);
  382. \draw[fill=c4] (0.7,-0.8) rectangle (0.9,-1.0);
  383. \draw[fill=c4] (0.7,-1.0) rectangle (0.9,-1.2);
  384. \draw[fill=c4] (0.7,-1.2) rectangle (0.9,-1.4);
  385. \draw[fill=c4] (0.7,-1.4) rectangle (0.9,-1.6);
  386. \end{tikzpicture}%>>>
  387. \end{columns}
  388. \end{frame}
  389. %>>>
  390. \begin{frame}[t,fragile] \frametitle{Instruction latency and throughput}{} %<<<
  391. \vspace{-1em}
  392. \begin{columns}[t]
  393. \column{0.45\textwidth}
  394. \footnotesize
  395. \begin{overprint}
  396. \onslide<1-2>%<<<
  397. \begin{minted}[
  398. frame=lines,
  399. fontsize=\footnotesize,
  400. linenos,
  401. gobble=10,
  402. mathescape
  403. ]{C++}
  404. sctl::Vec<double,8> x[8], one = 1;
  405. // ... initialize x
  406. double T = -omp_get_wtime();
  407. for (long i = 0; i < 1000000000L; i++) {
  408. x[0] = one + x[0];
  409. x[1] = one + x[1];
  410. x[2] = one + x[2];
  411. x[3] = one + x[3];
  412. ...
  413. x[8] = one + x[8];
  414. }
  415. T += omp_get_wtime();
  416. std::cout<<"T = "<< T <<'\n';
  417. std::cout<<"cycles/iter = "<< 3.3*T <<'\n';
  418. \end{minted}
  419. %>>>
  420. \onslide<3->%<<<
  421. \begin{minted}[
  422. frame=lines,
  423. fontsize=\footnotesize,
  424. linenos,
  425. gobble=10,
  426. mathescape
  427. ]{C++}
  428. sctl::Vec<double,8> x[8], one = 1;
  429. // ... initialize x
  430. double T = -omp_get_wtime();
  431. for (long i = 0; i < 1000000000L; i++) {
  432. x[0] = one / x[0];
  433. x[1] = one / x[1];
  434. x[2] = one / x[2];
  435. x[3] = one / x[3];
  436. ...
  437. x[8] = one / x[8];
  438. }
  439. T += omp_get_wtime();
  440. std::cout<<"T = "<< T <<'\n';
  441. std::cout<<"cycles/iter = "<< 3.3*T <<'\n';
  442. \end{minted}
  443. %>>>
  444. \end{overprint}
  445. \column{0.1\textwidth}
  446. \column{0.45\textwidth}
  447. \begin{overprint}
  448. \onslide<2>%<<<
  449. \begin{minted}[gobble=8,fontsize=\footnotesize]{text}
  450. T = 1.22806
  451. cycles/iter = 4.05259
  452. \end{minted}
  453. \textcolor{red}{\qquad 16 adds/cycle!}
  454. %>>>
  455. \onslide<3>%<<<
  456. \begin{minted}[gobble=8,fontsize=\footnotesize]{text}
  457. T = 1.22806
  458. cycles/iter = 4.05259
  459. \end{minted}
  460. \textcolor{red}{\qquad 16 adds/cycle!}
  461. \vspace{0.5em}
  462. \qquad --- floating-point division ---
  463. %>>>
  464. \onslide<4>%<<<
  465. \begin{minted}[gobble=8,fontsize=\footnotesize]{text}
  466. T = 1.22806
  467. cycles/iter = 4.05259
  468. \end{minted}
  469. \textcolor{red}{\qquad 16 adds/cycle!}
  470. \vspace{0.5em}
  471. \qquad --- floating-point division ---
  472. \begin{minted}[gobble=8,fontsize=\footnotesize]{text}
  473. T = 39.1521
  474. cycles/iter = 129.202
  475. \end{minted}
  476. \textcolor{red}{\qquad $\sim 32\times$ slower!}
  477. %>>>
  478. \onslide<5->%<<<
  479. \begin{minted}[gobble=8,fontsize=\footnotesize]{text}
  480. T = 1.22806
  481. cycles/iter = 4.05259
  482. \end{minted}
  483. \textcolor{red}{\qquad 16 adds/cycle!}
  484. \vspace{0.5em}
  485. \qquad --- floating-point division ---
  486. \begin{minted}[gobble=8,fontsize=\footnotesize]{text}
  487. T = 39.1521
  488. cycles/iter = 129.202
  489. \end{minted}
  490. \textcolor{red}{\qquad $\sim 32\times$ slower!}
  491. \footnotesize
  492. \vspace{0.5em}
  493. \quad {\normalsize Fast}: bitwise ops, int \& fp ops ($+,-,*$)
  494. \vspace{0.2em}
  495. \quad {\normalsize Slow}: branches, $/, {\sqrt \cdot}, \sin, \cos, \cdots$
  496. %>>>
  497. \end{overprint}
  498. \end{columns}
  499. \end{frame}
  500. %>>>
  501. \begin{frame}[fragile] \frametitle{Pipelining polynomial eval (Horner's rule)} %<<<
  502. \begin{columns}[T]
  503. \column{0.15\textwidth}
  504. {\bf Input:} \\
  505. x,~a,~b,~c,~d,~e,~f,~g,~h \\
  506. \vspace{1em}
  507. {\bf Compute:} \\
  508. ((((((ax+b)x+c)x+d)x\\
  509. ~~~~+e)x+f)x+g)x+h
  510. \column{0.6\textwidth}
  511. \resizebox{0.88\textwidth}{!}{\begin{tikzpicture}[nodes={draw, ellipse}, latex-]
  512. \node{$\times, +$}
  513. child { node {$\times, +$}
  514. child { node {$\times, +$}
  515. child { node {$\times, +$}
  516. child { node {$\times, +$}
  517. child { node {$\times, +$}
  518. child { node {$\times, +$}
  519. child { node {a} }
  520. child { node {x} }
  521. child { node {b} }
  522. }
  523. child { node {x} }
  524. child { node {c} }
  525. }
  526. child { node {x} }
  527. child { node {d} }
  528. }
  529. child { node {x} }
  530. child { node {e} }
  531. }
  532. child { node {x} }
  533. child { node {f} }
  534. }
  535. child { node {x} }
  536. child { node {g} }
  537. }
  538. child { node {x} }
  539. child { node {h} };
  540. \end{tikzpicture}}%
  541. \column{0.25\textwidth}
  542. \textcolor{c1}{u = a * x + b}\only<1-4>{ $\leftarrow$} \\
  543. \textcolor{c2}{v = u * x + c}\only<5-8>{ $\leftarrow$} \\
  544. \textcolor{c3}{w = v * x + d}\only<9-12>{ $\leftarrow$} \\
  545. \textcolor{c4}{p = w * x + e}\only<13-16>{ $\leftarrow$} \\
  546. \textcolor{c5}{q = p * x + f}\only<17-20>{ $\leftarrow$} \\
  547. \textcolor{c6}{r = q * x + g}\only<21-24>{ $\leftarrow$} \\
  548. \textcolor{c7}{s = r * x + h}\only<25-28>{ $\leftarrow$} \\
  549. \vspace{1em}
  550. {\bf Pipeline:}
  551. \vspace{0.5em}
  552. \resizebox{0.99\textwidth}{!}{\begin{tikzpicture}
  553. \draw[draw=none] (0,0) rectangle (4,1);
  554. \only<1-28>{
  555. \draw[fill=white] (0,0) rectangle (1,0.5);
  556. \draw[fill=white] (1,0) rectangle (2,0.5);
  557. \draw[fill=white] (2,0) rectangle (3,0.5);
  558. \draw[fill=white] (3,0) rectangle (4,0.5);
  559. \draw[fill=white] (0,0.6) rectangle (1,1.1);
  560. \draw[fill=white] (1,0.6) rectangle (2,1.1);
  561. \draw[fill=white] (2,0.6) rectangle (3,1.1);
  562. \draw[fill=white] (3,0.6) rectangle (4,1.1);
  563. }
  564. \only<1>{\draw[fill=c1] (0,0) rectangle (1,0.5);}
  565. \only<2>{\draw[fill=c1] (1,0) rectangle (2,0.5);}
  566. \only<3>{\draw[fill=c1] (2,0) rectangle (3,0.5);}
  567. \only<4>{\draw[fill=c1] (3,0) rectangle (4,0.5);}
  568. \only<5>{\draw[fill=c2] (0,0) rectangle (1,0.5);}
  569. \only<6>{\draw[fill=c2] (1,0) rectangle (2,0.5);}
  570. \only<7>{\draw[fill=c2] (2,0) rectangle (3,0.5);}
  571. \only<8>{\draw[fill=c2] (3,0) rectangle (4,0.5);}
  572. \only<9 >{\draw[fill=c3] (0,0) rectangle (1,0.5);}
  573. \only<10>{\draw[fill=c3] (1,0) rectangle (2,0.5);}
  574. \only<11>{\draw[fill=c3] (2,0) rectangle (3,0.5);}
  575. \only<12>{\draw[fill=c3] (3,0) rectangle (4,0.5);}
  576. \only<13>{\draw[fill=c4] (0,0) rectangle (1,0.5);}
  577. \only<14>{\draw[fill=c4] (1,0) rectangle (2,0.5);}
  578. \only<15>{\draw[fill=c4] (2,0) rectangle (3,0.5);}
  579. \only<16>{\draw[fill=c4] (3,0) rectangle (4,0.5);}
  580. \only<17>{\draw[fill=c5] (0,0) rectangle (1,0.5);}
  581. \only<18>{\draw[fill=c5] (1,0) rectangle (2,0.5);}
  582. \only<19>{\draw[fill=c5] (2,0) rectangle (3,0.5);}
  583. \only<20>{\draw[fill=c5] (3,0) rectangle (4,0.5);}
  584. \only<21>{\draw[fill=c6] (0,0) rectangle (1,0.5);}
  585. \only<22>{\draw[fill=c6] (1,0) rectangle (2,0.5);}
  586. \only<23>{\draw[fill=c6] (2,0) rectangle (3,0.5);}
  587. \only<24>{\draw[fill=c6] (3,0) rectangle (4,0.5);}
  588. \only<25>{\draw[fill=c7] (0,0) rectangle (1,0.5);}
  589. \only<26>{\draw[fill=c7] (1,0) rectangle (2,0.5);}
  590. \only<27>{\draw[fill=c7] (2,0) rectangle (3,0.5);}
  591. \only<28>{\draw[fill=c7] (3,0) rectangle (4,0.5);}
  592. \only<29>{\node at (2,0.75) {\Large 28 cycles};}
  593. \only<29>{\node at (2,0.25) {\Large 12.5\% utilization!};}
  594. \end{tikzpicture}}%
  595. \end{columns}
  596. % Helmholtz kernel code example
  597. % sample sort code
  598. % evaluating a polynomial
  599. % what we think happens
  600. % reality!
  601. \end{frame}
  602. %>>>
  603. \begin{frame}[t,fragile] \frametitle{Pipelining: polynomial eval (Estrin's method)} %<<<
  604. \begin{columns}[t]
  605. \column{0.75\textwidth}
  606. {\bf Input:} \\
  607. x,~a,~b,~c,~d,~e,~f,~g,~h \\
  608. \vspace{1em}
  609. {\bf Compute:} \\
  610. ((ax+b)x\textsuperscript{2}+(cx+d))x\textsuperscript{4}+(ex+f)x\textsuperscript{2}+(gx+h)
  611. \resizebox{0.99\textwidth}{!}{\begin{tikzpicture}[
  612. baseline,
  613. level distance=15mm,
  614. %text depth=.5em,
  615. %text height=.8em,
  616. level 1/.style={sibling distance=10em},
  617. level 2/.style={sibling distance=5em},
  618. level 3/.style={sibling distance=2.5em},
  619. level 4/.style={sibling distance=1em},
  620. nodes={draw, ellipse}, latex-]
  621. \node{$\times,+$}
  622. child { node {$\times,+$}
  623. child { node {$\times,+$}
  624. child { node {a} }
  625. child { node {x} }
  626. child { node {b} }
  627. }
  628. child { node {$\times$}
  629. child { node {x} }
  630. }
  631. child { node {$\times,+$}
  632. child { node {c} }
  633. child { node {x} }
  634. child { node {d} }
  635. }
  636. }
  637. child { node {$\times$}
  638. child { node {$\times$}
  639. child { node {x} }
  640. }
  641. }
  642. child { node {$\times,+$}
  643. child { node {$\times,+$}
  644. child { node {e} }
  645. child { node {x} }
  646. child { node {f} }
  647. }
  648. child { node {$\times$}
  649. child { node {x} }
  650. }
  651. child { node {$\times,+$}
  652. child { node {g} }
  653. child { node {x} }
  654. child { node {h} }
  655. }
  656. };
  657. \end{tikzpicture}}%
  658. \column{0.25\textwidth}
  659. %<<<
  660. \textcolor{c1}{x\textsuperscript{2} = x * x} \only<1-4>{ $\leftarrow$} \\ %
  661. \textcolor{c2}{x\textsuperscript{4} = x\textsuperscript{2} * x\textsuperscript{2}}\only<5-8>{ $\leftarrow$} \\ %
  662. \textcolor{c3}{u = a * x + b} \only<1-4>{ $\leftarrow$} \\
  663. \textcolor{c4}{v = c * x + d} \only<2-5>{ $\leftarrow$} \\ %
  664. \textcolor{c5}{w = e * x + f} \only<2-5>{ $\leftarrow$} \\
  665. \textcolor{c6}{p = g * x + h} \only<3-6>{ $\leftarrow$} \\ %
  666. \textcolor{c7}{q = u * x\textsuperscript{2} + v} \only<6-9>{ $\leftarrow$} \\ %
  667. \textcolor{c8}{r = w * x\textsuperscript{2} + p} \only<7-10>{ $\leftarrow$} \\ %
  668. \textcolor{c9}{s = q * x\textsuperscript{4} + r} \only<11-14>{ $\leftarrow$} \\ %
  669. \vspace{0.5em}
  670. {\bf Pipeline:}
  671. \vspace{0.1em}
  672. \resizebox{0.99\textwidth}{!}{\begin{tikzpicture}
  673. \draw[draw=none] (0,0) rectangle (4,1);
  674. \only<1-14>{
  675. \draw[fill=white] (0,0) rectangle (1,0.5);
  676. \draw[fill=white] (1,0) rectangle (2,0.5);
  677. \draw[fill=white] (2,0) rectangle (3,0.5);
  678. \draw[fill=white] (3,0) rectangle (4,0.5);
  679. \draw[fill=white] (0,0.6) rectangle (1,1.1);
  680. \draw[fill=white] (1,0.6) rectangle (2,1.1);
  681. \draw[fill=white] (2,0.6) rectangle (3,1.1);
  682. \draw[fill=white] (3,0.6) rectangle (4,1.1);
  683. }
  684. \only<1>{\draw[fill=c1] (0,0) rectangle (1,0.5);}
  685. \only<2>{\draw[fill=c1] (1,0) rectangle (2,0.5);}
  686. \only<3>{\draw[fill=c1] (2,0) rectangle (3,0.5);}
  687. \only<4>{\draw[fill=c1] (3,0) rectangle (4,0.5);}
  688. \only<5>{\draw[fill=c2] (0,0) rectangle (1,0.5);}
  689. \only<6>{\draw[fill=c2] (1,0) rectangle (2,0.5);}
  690. \only<7>{\draw[fill=c2] (2,0) rectangle (3,0.5);}
  691. \only<8>{\draw[fill=c2] (3,0) rectangle (4,0.5);}
  692. \only<1>{\draw[fill=c3] (0,0.6) rectangle (1,1.1);}
  693. \only<2>{\draw[fill=c3] (1,0.6) rectangle (2,1.1);}
  694. \only<3>{\draw[fill=c3] (2,0.6) rectangle (3,1.1);}
  695. \only<4>{\draw[fill=c3] (3,0.6) rectangle (4,1.1);}
  696. \only<2>{\draw[fill=c4] (0,0) rectangle (1,0.5);}
  697. \only<3>{\draw[fill=c4] (1,0) rectangle (2,0.5);}
  698. \only<4>{\draw[fill=c4] (2,0) rectangle (3,0.5);}
  699. \only<5>{\draw[fill=c4] (3,0) rectangle (4,0.5);}
  700. \only<2>{\draw[fill=c5] (0,0.6) rectangle (1,1.1);}
  701. \only<3>{\draw[fill=c5] (1,0.6) rectangle (2,1.1);}
  702. \only<4>{\draw[fill=c5] (2,0.6) rectangle (3,1.1);}
  703. \only<5>{\draw[fill=c5] (3,0.6) rectangle (4,1.1);}
  704. \only<3>{\draw[fill=c6] (0,0) rectangle (1,0.5);}
  705. \only<4>{\draw[fill=c6] (1,0) rectangle (2,0.5);}
  706. \only<5>{\draw[fill=c6] (2,0) rectangle (3,0.5);}
  707. \only<6>{\draw[fill=c6] (3,0) rectangle (4,0.5);}
  708. \only<6>{\draw[fill=c7] (0,0) rectangle (1,0.5);}
  709. \only<7>{\draw[fill=c7] (1,0) rectangle (2,0.5);}
  710. \only<8>{\draw[fill=c7] (2,0) rectangle (3,0.5);}
  711. \only<9>{\draw[fill=c7] (3,0) rectangle (4,0.5);}
  712. \only<7>{\draw[fill=c8] (0,0) rectangle (1,0.5);}
  713. \only<8>{\draw[fill=c8] (1,0) rectangle (2,0.5);}
  714. \only<9>{\draw[fill=c8] (2,0) rectangle (3,0.5);}
  715. \only<10>{\draw[fill=c8] (3,0) rectangle (4,0.5);}
  716. \only<11>{\draw[fill=c9] (0,0) rectangle (1,0.5);}
  717. \only<12>{\draw[fill=c9] (1,0) rectangle (2,0.5);}
  718. \only<13>{\draw[fill=c9] (2,0) rectangle (3,0.5);}
  719. \only<14>{\draw[fill=c9] (3,0) rectangle (4,0.5);}
  720. \only<15>{\node at (2,0.75) {\Large 14 cycles};}
  721. \only<15>{\node at (2,0.25) {\Large 2\times speedup!};}
  722. \end{tikzpicture}}%
  723. %>>>
  724. \end{columns}
  725. % Helmholtz kernel code example
  726. % sample sort code
  727. % evaluating a polynomial
  728. % what we think happens
  729. % reality!
  730. \end{frame}
  731. %>>>
  732. \begin{frame}[t,fragile] \frametitle{Polynomial evaluation: actual performance} %<<<
  733. \vspace{-1em}
  734. \begin{columns}[t]
  735. \column{0.55\textwidth}
  736. \footnotesize
  737. \begin{overprint}
  738. \onslide<1>%<<<
  739. \begin{minted}[
  740. frame=lines,
  741. fontsize=\footnotesize,
  742. linenos,
  743. gobble=10,
  744. mathescape
  745. ]{C++}
  746. // Horner's rule
  747. for (long i = 0; i < 1000000000L; i++) {
  748. x = (((((a*x+b)*x+c)*x+d)*x+e)*x+f*x+g)*x+h;
  749. }
  750. \end{minted}
  751. \begin{minted}[
  752. frame=lines,
  753. fontsize=\footnotesize,
  754. linenos,
  755. gobble=10,
  756. mathescape
  757. ]{C++}
  758. // Estrin's method
  759. for (long i = 0; i < 1000000000L; i++) {
  760. double x2 = x * x;
  761. double x4 = x2 * x2;
  762. x = ((a*x+b)*x2+(c*x+d))*x4+(e*x+f)*x2+(g*x+h);
  763. }
  764. \end{minted}
  765. %>>>
  766. \onslide<2>%<<<
  767. \begin{minted}[
  768. frame=lines,
  769. fontsize=\footnotesize,
  770. linenos,
  771. gobble=10,
  772. mathescape
  773. ]{C++}
  774. // Horner's rule
  775. for (long i = 0; i < 1000000000L; i++) {
  776. x = (((((a*x+b)*x+c)*x+d)*x+e)*x+f*x+g)*x+h;
  777. }
  778. \end{minted}
  779. \begin{minted}[
  780. frame=lines,
  781. fontsize=\footnotesize,
  782. linenos,
  783. gobble=10,
  784. mathescape
  785. ]{C++}
  786. // Estrin's method (unrolled)
  787. for (long i = 0; i < 1000000000L; i++) {
  788. double x2 = x * x;
  789. double x4 = x2 * x2;
  790. double u = a * x + b;
  791. double v = c * x + d;
  792. double w = e * x + f;
  793. double p = g * x + h;
  794. double q = u * x2 + v;
  795. double r = w * x2 + p;
  796. x = q * x4 + r;
  797. }
  798. \end{minted}
  799. %>>>
  800. \end{overprint}
  801. \column{0.05\textwidth}
  802. \column{0.35\textwidth}
  803. \begin{overprint}
  804. \onslide<1>%<<<
  805. \begin{minted}[gobble=8,fontsize=\footnotesize]{text}
  806. Using Horner's rule:
  807. T = 8.82432
  808. cycles/iter = 29.1203
  809. Using Estrin's method:
  810. T = 5.7813
  811. cycles/iter = 19.0783
  812. \end{minted}
  813. \textcolor{red}{\qquad only $1.5\times$ speedup :(}
  814. %>>>
  815. \onslide<2>%<<<
  816. \begin{minted}[gobble=8,fontsize=\footnotesize]{text}
  817. Using Horner's rule:
  818. T = 8.82432
  819. cycles/iter = 29.1203
  820. Using Estrin's method (unrolled):
  821. T = 4.5794
  822. cycles/iter = 15.112
  823. \end{minted}
  824. \textcolor{red}{\qquad $1.9\times$ speedup!}
  825. %>>>
  826. \end{overprint}
  827. \end{columns}
  828. % perf - show stalled cycles
  829. \end{frame}
  830. %>>>
  831. \begin{frame}[t] \frametitle{Libraries for special function evaluation} %<<<
  832. \vspace{-1.1em}
  833. \begin{columns}[t]
  834. \column{0.6\textwidth}
  835. \small
  836. \begin{itemize}
  837. \item Baobzi (adaptive fast function interpolator) \\
  838. {\footnotesize
  839. \url{https://github.com/flatironinstitute/baobzi}}
  840. \item Agner Fog's Vector Class Library
  841. \item SLEEF Vectoried Math Library
  842. \item FORTRAN native routines
  843. \item C++ Standard Library
  844. \item Eigen
  845. \item Boost
  846. \item AMD Math Library (LibM)
  847. \item GNU Scientific Library (GSL)
  848. \item Scientific Computing Template Library (SCTL)
  849. \end{itemize}
  850. \column{0.4\textwidth}
  851. \center
  852. \resizebox{0.95\textwidth}{!}{ %<<<
  853. \begin{tabular}{r r r r }
  854. \toprule
  855. func & name & cycles/eval \\
  856. \midrule
  857. bessel\_J0 & baobzi & 20.8 \\
  858. bessel\_J0 & fort & 200.9 \\
  859. bessel\_J0 & gsl & 504.5 \\
  860. bessel\_J0 & boost & 542.9 \\
  861. \midrule
  862. sin & agnerfog & 3.2 \\
  863. sin & sctl & 3.6 \\
  864. sin & sleef & 4.6 \\
  865. sin & amdlibm & 6.9 \\
  866. sin & stl & 32.9 \\
  867. sin & eigen & 33.1 \\
  868. sin & gsl & 149.4 \\
  869. \bottomrule
  870. \end{tabular}}%>>>
  871. \footnotesize
  872. Robert Blackwell - sf\_benchmarks : \\
  873. {\tiny \url{https://github.com/flatironinstitute/sf_benchmarks}}
  874. \end{columns}
  875. \end{frame}
  876. %>>>
  877. \begin{frame}[t] \frametitle{GEMM micro-kernel}{} %<<<
  878. \vspace{-1em}
  879. \begin{columns}[t]
  880. \column{0.5\textwidth}
  881. \begin{itemize}
  882. \setlength\itemsep{0.75em}
  883. \item This is pedagogical -- don't write your own GEMM (use BLAS)
  884. \item Peak FLOP rate (Skylake core)
  885. \begin{itemize}
  886. \item FMA (1+1 per cycle) units ($\times 2$)
  887. \item 512-bit vectors ($\times 8$ for doubles)
  888. \item 3.3GHz clock rate
  889. \item $= 105.6$ GFLOP/s
  890. \item How close can we get to the peak?
  891. \end{itemize}
  892. \item Matrix sizes: M, N, K
  893. \item Assume column-major ordering
  894. \end{itemize}
  895. \column{0.5\textwidth}
  896. \center
  897. \resizebox{0.99\textwidth}{!}{\begin{tikzpicture} %<<<
  898. \node at (-0.5,-1) {$M$};
  899. \node at (1,0.5) {$N$};
  900. \draw[latex-latex, thick] (0,0.25) -- (2,0.25);
  901. \draw[latex-latex, thick] (-0.25,0) -- (-0.25,-2);
  902. \fill[c2] (0,0) rectangle (2,-2);
  903. \draw[step=0.25,thick, darkgray] (0,0) grid (2,-2);
  904. \node at (1,-1) {\Large C};
  905. \node at (2.5,-1) {$=$};
  906. \node at (4.25,0.5) {$K$};
  907. \draw[latex-latex, thick] (3,0.25) -- (5.5,0.25);
  908. \fill[c3] (3,0) rectangle (5.5,-2);
  909. \draw[step=0.25,thick, darkgray] (2.99,0) grid (5.5,-2);
  910. \node at (4.25,-1) {\Large A};
  911. \node at (6,-1) {$\times$};
  912. \fill[c4] (6.5,0) rectangle (8.5,-2.5);
  913. \draw[step=0.25,thick, darkgray] (6.49,0) grid (8.5,-2.5);
  914. \node at (7.5,-1.25) {\Large B};
  915. \end{tikzpicture}}%>>>
  916. \vspace{1.5em}
  917. \resizebox{0.4\textwidth}{!}{\begin{tikzpicture} %<<<
  918. \fill[c2] (0,0) rectangle (1.5,-1.5);
  919. \draw[step=0.25,thick, darkgray] (0,0) grid (1.5,-1.5);
  920. \draw[-latex, thick] (0.125,-0.125) -- (0.125,-1.375);
  921. \draw[-latex, thick] (0.375,-0.125) -- (0.375,-1.375);
  922. \draw[-latex, thick] (0.625,-0.125) -- (0.625,-1.375);
  923. \end{tikzpicture}}%>>>
  924. \end{columns}
  925. \end{frame}
  926. %>>>
  927. \begin{frame}[t,fragile] \frametitle{GEMM micro-kernel}{} %<<<
  928. \vspace{-1em}
  929. \begin{columns}[t]
  930. \column{0.55\textwidth}
  931. \begin{overprint}
  932. \onslide<1-2>%<<<
  933. \begin{minted}[
  934. frame=lines,
  935. fontsize=\scriptsize,
  936. linenos,
  937. gobble=8,
  938. mathescape
  939. ]{C++}
  940. template <int M, int N, int K>
  941. void GEMM_ker_naive(double* C, double* A, double* B) {
  942. for (int k = 0; k < K; k++)
  943. for (int j = 0; j < M; j++)
  944. for (int i = 0; i < M; i++)
  945. C[i+j*M] += A[i+k*M] * B[k+K*j];
  946. }
  947. int main(int argc, char* argv) {
  948. constexpr int M = 8, N = 8, K = 8;
  949. double* C = new double[M*N];
  950. double* A = new double[M*K];
  951. double* B = new double[K*N];
  952. // .. init A, B, C
  953. long L = 1e6;
  954. double T = -omp_get_wtime();
  955. for (long i = 0; i < L; i++)
  956. GEMM_ker_naive<M,N,K>(C, A, B);
  957. T += omp_get_wtime();
  958. std::cout<<"FLOP rate = "<<
  959. 2*M*N*K*L/T/1e9 << "GFLOP/s\n";
  960. \end{minted}
  961. %>>>
  962. \onslide<3-4>%<<<
  963. \begin{minted}[
  964. frame=lines,
  965. fontsize=\scriptsize,
  966. linenos,
  967. gobble=8,
  968. mathescape
  969. ]{C++}
  970. template <int M, int N, int K>
  971. void GEMM_ker_vec(double* C, double* A, double* B) {
  972. using Vec = sctl::Vec<double,M>;
  973. Vec Cv[N];
  974. for (int j = 0; j < N; j++)
  975. Cv[j] = Vec::Load(C+j*M);
  976. for (int k = 0; k < K; k++) {
  977. const Vec Av = Vec::Load(A+k*M);
  978. double* B_ = B + k;
  979. for (int j = 0; j < N; j++) {
  980. Cv[j] = Av * B_[K*j] + Cv[j];
  981. }
  982. }
  983. for (int j = 0; j < N; j++)
  984. Cv[j].Store(C+j*M);
  985. }
  986. \end{minted}
  987. %>>>
  988. \onslide<5-6>%<<<
  989. \begin{minted}[
  990. frame=lines,
  991. fontsize=\scriptsize,
  992. linenos,
  993. gobble=8,
  994. mathescape
  995. ]{C++}
  996. template <int M, int N, int K>
  997. void GEMM_ker_vec_unrolled(double* C, double* A, double* B) {
  998. using Vec = sctl::Vec<double,M>;
  999. Vec Cv[N];
  1000. #pragma GCC unroll (8)
  1001. for (int j = 0; j < N; j++)
  1002. Cv[j] = Vec::Load(C+j*M);
  1003. #pragma GCC unroll (8)
  1004. for (int k = 0; k < K; k++) {
  1005. const Vec Av = Vec::Load(A+k*M);
  1006. double* B_ = B + k;
  1007. #pragma GCC unroll (8)
  1008. for (int j = 0; j < N; j++) {
  1009. Cv[j] = Av * B_[j*K] + Cv[j];
  1010. }
  1011. }
  1012. #pragma GCC unroll (8)
  1013. for (int j = 0; j < N; j++)
  1014. Cv[j].Store(C+j*M);
  1015. }
  1016. \end{minted}
  1017. %>>>
  1018. \end{overprint}
  1019. \column{0.05\textwidth}
  1020. \column{0.4\textwidth}
  1021. \begin{overprint}
  1022. \onslide<2-3>%<<<
  1023. \begin{minted}[gobble=8,fontsize=\footnotesize]{text}
  1024. M = N = K = 8
  1025. GEMM (naive):
  1026. FLOP rate = 5.99578 GFLOP/s
  1027. \end{minted}
  1028. %>>>
  1029. \onslide<4-5>%<<<
  1030. \begin{minted}[gobble=8,fontsize=\footnotesize]{text}
  1031. M = N = K = 8
  1032. GEMM (naive):
  1033. FLOP rate = 5.99578 GFLOP/s
  1034. GEMM (vectorized):
  1035. FLOP rate = 29.3319 GFLOP/s
  1036. \end{minted}
  1037. %>>>
  1038. \onslide<6>%<<<
  1039. \begin{minted}[gobble=8,fontsize=\footnotesize]{text}
  1040. M = N = K = 8
  1041. GEMM (naive):
  1042. FLOP rate = 5.99578 GFLOP/s
  1043. GEMM (vectorized):
  1044. FLOP rate = 29.3319 GFLOP/s
  1045. GEMM (vectorized & unrolled):
  1046. FLOP rate = 38.5658 GFLOP/s
  1047. \end{minted}
  1048. \textcolor{red}{\qquad 36.5\% of peak}
  1049. %>>>
  1050. \end{overprint}
  1051. \end{columns}
  1052. % start with triple loop
  1053. % compiler options
  1054. % loop unrolling
  1055. % __restrict__
  1056. %
  1057. \end{frame}
  1058. %>>>
  1059. \begin{frame}[t,fragile] \frametitle{GEMM micro-kernel}{} %<<<
  1060. \vspace{-1em}
  1061. \begin{columns}[t]
  1062. \column{0.55\textwidth}
  1063. \center
  1064. \includegraphics[width=0.99\textwidth]{figs/blis-micro-kernel}
  1065. {\scriptsize Source: BLIS framework [Van Zee and van de Geijn 2015]}
  1066. \column{0.05\textwidth}
  1067. \column{0.4\textwidth}
  1068. \begin{overprint}
  1069. \onslide<1>%<<<
  1070. \begin{minted}[gobble=8,fontsize=\footnotesize]{text}
  1071. M = 8, N = 10, K = 40
  1072. \end{minted}
  1073. \textcolor{red}{\qquad 71\% of peak!}
  1074. %>>>
  1075. \onslide<2>%<<<
  1076. \begin{minted}[gobble=8,fontsize=\footnotesize]{text}
  1077. M = 8, N = 10, K = 48
  1078. GEMM (naive):
  1079. FLOP rate = 7.9677 GFLOP/s
  1080. GEMM (vectorized):
  1081. FLOP rate = 65.8419 GFLOP/s
  1082. GEMM (vectorized & unrolled):
  1083. FLOP rate = 74.9756 GFLOP/s
  1084. \end{minted}
  1085. \textcolor{red}{\qquad 71\% of peak!}
  1086. %>>>
  1087. \end{overprint}
  1088. \end{columns}
  1089. % start with triple loop
  1090. % compiler options
  1091. % loop unrolling
  1092. % __restrict__
  1093. %
  1094. \end{frame}
  1095. %>>>
  1096. \begin{frame} \frametitle{Instruction-level parallelism -- summary}{} %<<<
  1097. \begin{itemize}
  1098. \item ..
  1099. \end{itemize}
  1100. Resources
  1101. %\begin{itemize}
  1102. % \item Agner Fog: optimization guide
  1103. % \item Intel optimization guide
  1104. %\end{itemize}
  1105. % Use fast operations instead of slow
  1106. % Cast all computations in additions, multiplications, bitwise ops (eg. baobzi)
  1107. % Avoid expensive ops (div), branches
  1108. % Branches hurt performance significantly
  1109. % vectorization
  1110. % data arrangement: AoS vs SoA
  1111. % out-of-order execution, pipelining, vectorization:
  1112. % - refactor code to expose instruction level parallelism (sometimes even at the cost of extra work)
  1113. % batch operations, loop unrolling/fixed-length loops, expose instruction level parallelism
  1114. % benefits from fixed-size blocking (compiler can unroll)
  1115. % loops have conditionals, so unrolling is difficult
  1116. %%%%%%%%%%%%%%% maybe
  1117. % unaligned memory accesses
  1118. % show penalty from branches
  1119. % vector dot product: show data dependency stalls
  1120. %%%%%%%%%%%%%%%%%%% not needed
  1121. % remove un-necessary operations (pre-allocate memory)
  1122. % reduce number of operations (caching)
  1123. \end{frame}
  1124. %>>>