ilp.tex 34 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015
  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 one scalar operation at a time
  69. \item one operation per clock cycle
  70. \item sequentially and in order
  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,0) {\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 (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 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. % coding example
  262. \end{frame}
  263. %>>>
  264. \begin{frame}[t] \frametitle{SIMD vector instructions}{} %<<<
  265. \begin{columns}[t]
  266. \column{0.7\textwidth}
  267. \only<1>{
  268. \begin{itemize}
  269. \setlength\itemsep{1em}
  270. \item Think in vectors instead of scalars (float, double)
  271. \item Re-organize computations as vector operations
  272. \begin{itemize}
  273. \item Struct-of-arrays (SOA) \\
  274. $\{x_1,y_1,z_1, ~~x_2,y_2,z_2, \cdots, ~~x_n,y_n,z_n\}$
  275. \item Array-of-struct (AOS) \\
  276. $\{x_1,\cdots, x_n, ~~y_1,\cdots, y_n, ~~z_1,\cdots, z_n\}$
  277. \end{itemize}
  278. \item Tell the compiler it is safe to use SIMD instructions
  279. \begin{itemize}
  280. \item most languages don't make it easy to specify when it is safe to vectorize (aliasing)
  281. \end{itemize}
  282. \end{itemize}
  283. }
  284. \only<2>{
  285. \begin{itemize}
  286. \setlength\itemsep{1em}
  287. \item {Auto vectorization:} \textcolor{red}{unreliable!}
  288. \begin{itemize}
  289. \item Compiler specific hints:\\
  290. {-fopt-info-vec-optimized} \\
  291. {\color{blue} \_\_builtin\_assume\_aligned(a, 32)} \\
  292. {\color{magenta} \#pragma ivdep}
  293. \item OpenMP 4.0: {\color{magenta} \#pragma omp simd}
  294. \end{itemize}
  295. \item {Assembly:} \textcolor{red}{too hard!}
  296. \item {Vector intrinsics:} \textcolor{red}{works but messy!}
  297. \begin{itemize}
  298. \item {\_mm512\_add\_pd(\_\_m512d, \_\_m512d)}
  299. \item {\_mm512\_mul\_pd(\_\_m512d, \_\_m512d)}
  300. \end{itemize}
  301. \item {C++ vector libraries:} \textcolor{green}{intuitive and clean}
  302. %\begin{itemize}
  303. % \item Vector objects, overloaded operators (+, -, *, $||$, \&\& etc)
  304. %\end{itemize}
  305. \end{itemize}
  306. }
  307. \only<3>{
  308. \begin{itemize}
  309. \setlength\itemsep{1em}
  310. \item {C++ vector libraries:} \textcolor{green}{intuitive and clean}
  311. \begin{itemize}
  312. \setlength\itemsep{1em}
  313. \item Vector objects, overloaded operators (+, -, *, $||$, \&\& etc)
  314. \item Vector Class Library - Agner Fog\\
  315. \url{https://github.com/vectorclass/version2}
  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. $ g++ -O3 -march=native -fopenmp test.cpp
  451. $ ./a.out
  452. T = 1.22806
  453. cycles/iter = 4.05259
  454. \end{minted}
  455. \textcolor{red}{\qquad 16 adds/cycle!}
  456. %>>>
  457. \onslide<3>%<<<
  458. \begin{minted}[gobble=8,fontsize=\footnotesize]{text}
  459. $ g++ -O3 -march=native -fopenmp test.cpp
  460. $ ./a.out
  461. T = 1.22806
  462. cycles/iter = 4.05259
  463. \end{minted}
  464. \textcolor{red}{\qquad 16 adds/cycle!}
  465. \vspace{0.5em}
  466. \qquad --- floating-point division ---
  467. %>>>
  468. \onslide<4>%<<<
  469. \begin{minted}[gobble=8,fontsize=\footnotesize]{text}
  470. $ g++ -O3 -march=native -fopenmp test.cpp
  471. $ ./a.out
  472. T = 1.22806
  473. cycles/iter = 4.05259
  474. \end{minted}
  475. \textcolor{red}{\qquad 16 adds/cycle!}
  476. \vspace{0.5em}
  477. \qquad --- floating-point division ---
  478. \begin{minted}[gobble=8,fontsize=\footnotesize]{text}
  479. $ g++ -O3 -march=native -fopenmp test.cpp
  480. $ ./a.out
  481. T = 39.1521
  482. cycles/iter = 129.202
  483. \end{minted}
  484. \textcolor{red}{\qquad $\sim 32\times$ slower!}
  485. %>>>
  486. \onslide<5->%<<<
  487. \begin{minted}[gobble=8,fontsize=\footnotesize]{text}
  488. $ g++ -O3 -march=native -fopenmp test.cpp
  489. $ ./a.out
  490. T = 1.22806
  491. cycles/iter = 4.05259
  492. \end{minted}
  493. \textcolor{red}{\qquad 16 adds/cycle!}
  494. \vspace{0.5em}
  495. \qquad --- floating-point division ---
  496. \begin{minted}[gobble=8,fontsize=\footnotesize]{text}
  497. $ g++ -O3 -march=native -fopenmp test.cpp
  498. $ ./a.out
  499. T = 39.1521
  500. cycles/iter = 129.202
  501. \end{minted}
  502. \textcolor{red}{\qquad $\sim 32\times$ slower!}
  503. \footnotesize
  504. \vspace{0.5em}
  505. \quad {\normalsize Fast}: bitwise ops, int \& fp ops ($+,-,*$)
  506. \vspace{0.2em}
  507. \quad {\normalsize Slow}: branches, $/, {\sqrt \cdot}, \sin, \cos, \cdots$
  508. %>>>
  509. \end{overprint}
  510. \end{columns}
  511. % coding example
  512. \end{frame}
  513. %>>>
  514. \begin{frame}[fragile] \frametitle{Pipelining polynomial eval (Horner's rule)} %<<<
  515. \begin{columns}[T]
  516. \column{0.15\textwidth}
  517. {\bf Input:} \\
  518. x,~a,~b,~c,~d,~e,~f,~g,~h \\
  519. \vspace{1em}
  520. {\bf Compute:} \\
  521. ((((((ax+b)x+c)x+d)x\\
  522. ~~~~+e)x+f)x+g)x+h
  523. \column{0.6\textwidth}
  524. \resizebox{0.88\textwidth}{!}{\begin{tikzpicture}[nodes={draw, ellipse}, latex-]
  525. \node{$\times, +$}
  526. child { node {$\times, +$}
  527. child { node {$\times, +$}
  528. child { node {$\times, +$}
  529. child { node {$\times, +$}
  530. child { node {$\times, +$}
  531. child { node {$\times, +$}
  532. child { node {a} }
  533. child { node {x} }
  534. child { node {b} }
  535. }
  536. child { node {x} }
  537. child { node {c} }
  538. }
  539. child { node {x} }
  540. child { node {d} }
  541. }
  542. child { node {x} }
  543. child { node {e} }
  544. }
  545. child { node {x} }
  546. child { node {f} }
  547. }
  548. child { node {x} }
  549. child { node {g} }
  550. }
  551. child { node {x} }
  552. child { node {h} };
  553. \end{tikzpicture}}%
  554. \column{0.25\textwidth}
  555. \textcolor{c1}{u = a * x + b}\only<1-4>{ $\leftarrow$} \\
  556. \textcolor{c2}{v = u * x + c}\only<5-8>{ $\leftarrow$} \\
  557. \textcolor{c3}{w = v * x + d}\only<9-12>{ $\leftarrow$} \\
  558. \textcolor{c4}{p = w * x + e}\only<13-16>{ $\leftarrow$} \\
  559. \textcolor{c5}{q = p * x + f}\only<17-20>{ $\leftarrow$} \\
  560. \textcolor{c6}{r = q * x + g}\only<21-24>{ $\leftarrow$} \\
  561. \textcolor{c7}{s = r * x + h}\only<25-28>{ $\leftarrow$} \\
  562. \vspace{1em}
  563. {\bf Pipeline:}
  564. \vspace{0.5em}
  565. \resizebox{0.99\textwidth}{!}{\begin{tikzpicture}
  566. \draw[draw=none] (0,0) rectangle (4,1);
  567. \only<1-28>{
  568. \draw[fill=white] (0,0) rectangle (1,0.5);
  569. \draw[fill=white] (1,0) rectangle (2,0.5);
  570. \draw[fill=white] (2,0) rectangle (3,0.5);
  571. \draw[fill=white] (3,0) rectangle (4,0.5);
  572. \draw[fill=white] (0,0.6) rectangle (1,1.1);
  573. \draw[fill=white] (1,0.6) rectangle (2,1.1);
  574. \draw[fill=white] (2,0.6) rectangle (3,1.1);
  575. \draw[fill=white] (3,0.6) rectangle (4,1.1);
  576. }
  577. \only<1>{\draw[fill=c1] (0,0) rectangle (1,0.5);}
  578. \only<2>{\draw[fill=c1] (1,0) rectangle (2,0.5);}
  579. \only<3>{\draw[fill=c1] (2,0) rectangle (3,0.5);}
  580. \only<4>{\draw[fill=c1] (3,0) rectangle (4,0.5);}
  581. \only<5>{\draw[fill=c2] (0,0) rectangle (1,0.5);}
  582. \only<6>{\draw[fill=c2] (1,0) rectangle (2,0.5);}
  583. \only<7>{\draw[fill=c2] (2,0) rectangle (3,0.5);}
  584. \only<8>{\draw[fill=c2] (3,0) rectangle (4,0.5);}
  585. \only<9 >{\draw[fill=c3] (0,0) rectangle (1,0.5);}
  586. \only<10>{\draw[fill=c3] (1,0) rectangle (2,0.5);}
  587. \only<11>{\draw[fill=c3] (2,0) rectangle (3,0.5);}
  588. \only<12>{\draw[fill=c3] (3,0) rectangle (4,0.5);}
  589. \only<13>{\draw[fill=c4] (0,0) rectangle (1,0.5);}
  590. \only<14>{\draw[fill=c4] (1,0) rectangle (2,0.5);}
  591. \only<15>{\draw[fill=c4] (2,0) rectangle (3,0.5);}
  592. \only<16>{\draw[fill=c4] (3,0) rectangle (4,0.5);}
  593. \only<17>{\draw[fill=c5] (0,0) rectangle (1,0.5);}
  594. \only<18>{\draw[fill=c5] (1,0) rectangle (2,0.5);}
  595. \only<19>{\draw[fill=c5] (2,0) rectangle (3,0.5);}
  596. \only<20>{\draw[fill=c5] (3,0) rectangle (4,0.5);}
  597. \only<21>{\draw[fill=c6] (0,0) rectangle (1,0.5);}
  598. \only<22>{\draw[fill=c6] (1,0) rectangle (2,0.5);}
  599. \only<23>{\draw[fill=c6] (2,0) rectangle (3,0.5);}
  600. \only<24>{\draw[fill=c6] (3,0) rectangle (4,0.5);}
  601. \only<25>{\draw[fill=c7] (0,0) rectangle (1,0.5);}
  602. \only<26>{\draw[fill=c7] (1,0) rectangle (2,0.5);}
  603. \only<27>{\draw[fill=c7] (2,0) rectangle (3,0.5);}
  604. \only<28>{\draw[fill=c7] (3,0) rectangle (4,0.5);}
  605. \only<29>{\node at (2,0.75) {\Large 28 cycles};}
  606. \only<29>{\node at (2,0.25) {\Large 12.5\% utilization!};}
  607. \end{tikzpicture}}%
  608. \end{columns}
  609. % Helmholtz kernel code example
  610. % sample sort code
  611. % evaluating a polynomial
  612. % what we think happens
  613. % reality!
  614. \end{frame}
  615. %>>>
  616. \begin{frame}[fragile] \frametitle{Pipelining: polynomial eval (Estrin's method)} %<<<
  617. \begin{columns}[T]
  618. \column{0.75\textwidth}
  619. {\bf Input:} \\
  620. x,~a,~b,~c,~d,~e,~f,~g,~h \\
  621. \vspace{1em}
  622. {\bf Compute:} \\
  623. ((ax+b)x\textsuperscript{2}+(cx+d))x\textsuperscript{4}+(ex+f)x\textsuperscript{2}+(gx+h)
  624. \resizebox{0.99\textwidth}{!}{\begin{tikzpicture}[
  625. baseline,
  626. level distance=15mm,
  627. %text depth=.5em,
  628. %text height=.8em,
  629. level 1/.style={sibling distance=10em},
  630. level 2/.style={sibling distance=5em},
  631. level 3/.style={sibling distance=2.5em},
  632. level 4/.style={sibling distance=1em},
  633. nodes={draw, ellipse}, latex-]
  634. \node{$\times,+$}
  635. child { node {$\times,+$}
  636. child { node {$\times,+$}
  637. child { node {a} }
  638. child { node {x} }
  639. child { node {b} }
  640. }
  641. child { node {$\times$}
  642. child { node {x} }
  643. }
  644. child { node {$\times,+$}
  645. child { node {c} }
  646. child { node {x} }
  647. child { node {d} }
  648. }
  649. }
  650. child { node {$\times$}
  651. child { node {$\times$}
  652. child { node {x} }
  653. }
  654. }
  655. child { node {$\times,+$}
  656. child { node {$\times,+$}
  657. child { node {e} }
  658. child { node {x} }
  659. child { node {f} }
  660. }
  661. child { node {$\times$}
  662. child { node {x} }
  663. }
  664. child { node {$\times,+$}
  665. child { node {g} }
  666. child { node {x} }
  667. child { node {h} }
  668. }
  669. };
  670. \end{tikzpicture}}%
  671. \column{0.25\textwidth}
  672. %<<<
  673. \textcolor{c1}{x\textsuperscript{2} = x * x} \only<1-4>{ $\leftarrow$} \\ %
  674. \textcolor{c2}{x\textsuperscript{4} = x\textsuperscript{2} * x\textsuperscript{2}}\only<5-8>{ $\leftarrow$} \\ %
  675. \textcolor{c3}{u = a * x + b} \only<1-4>{ $\leftarrow$} \\
  676. \textcolor{c4}{v = c * x + d} \only<2-5>{ $\leftarrow$} \\ %
  677. \textcolor{c5}{w = e * x + f} \only<2-5>{ $\leftarrow$} \\
  678. \textcolor{c6}{p = g * x + h} \only<3-6>{ $\leftarrow$} \\ %
  679. \textcolor{c7}{q = u * x\textsuperscript{2} + v} \only<6-9>{ $\leftarrow$} \\ %
  680. \textcolor{c8}{r = w * x\textsuperscript{2} + p} \only<7-10>{ $\leftarrow$} \\ %
  681. \textcolor{c9}{s = q * x\textsuperscript{4} + r} \only<11-14>{ $\leftarrow$} \\ %
  682. \vspace{0.5em}
  683. {\bf Pipeline:}
  684. \vspace{0.1em}
  685. \resizebox{0.99\textwidth}{!}{\begin{tikzpicture}
  686. \draw[draw=none] (0,0) rectangle (4,1);
  687. \only<1-14>{
  688. \draw[fill=white] (0,0) rectangle (1,0.5);
  689. \draw[fill=white] (1,0) rectangle (2,0.5);
  690. \draw[fill=white] (2,0) rectangle (3,0.5);
  691. \draw[fill=white] (3,0) rectangle (4,0.5);
  692. \draw[fill=white] (0,0.6) rectangle (1,1.1);
  693. \draw[fill=white] (1,0.6) rectangle (2,1.1);
  694. \draw[fill=white] (2,0.6) rectangle (3,1.1);
  695. \draw[fill=white] (3,0.6) rectangle (4,1.1);
  696. }
  697. \only<1>{\draw[fill=c1] (0,0) rectangle (1,0.5);}
  698. \only<2>{\draw[fill=c1] (1,0) rectangle (2,0.5);}
  699. \only<3>{\draw[fill=c1] (2,0) rectangle (3,0.5);}
  700. \only<4>{\draw[fill=c1] (3,0) rectangle (4,0.5);}
  701. \only<5>{\draw[fill=c2] (0,0) rectangle (1,0.5);}
  702. \only<6>{\draw[fill=c2] (1,0) rectangle (2,0.5);}
  703. \only<7>{\draw[fill=c2] (2,0) rectangle (3,0.5);}
  704. \only<8>{\draw[fill=c2] (3,0) rectangle (4,0.5);}
  705. \only<1>{\draw[fill=c3] (0,0.6) rectangle (1,1.1);}
  706. \only<2>{\draw[fill=c3] (1,0.6) rectangle (2,1.1);}
  707. \only<3>{\draw[fill=c3] (2,0.6) rectangle (3,1.1);}
  708. \only<4>{\draw[fill=c3] (3,0.6) rectangle (4,1.1);}
  709. \only<2>{\draw[fill=c4] (0,0) rectangle (1,0.5);}
  710. \only<3>{\draw[fill=c4] (1,0) rectangle (2,0.5);}
  711. \only<4>{\draw[fill=c4] (2,0) rectangle (3,0.5);}
  712. \only<5>{\draw[fill=c4] (3,0) rectangle (4,0.5);}
  713. \only<2>{\draw[fill=c5] (0,0.6) rectangle (1,1.1);}
  714. \only<3>{\draw[fill=c5] (1,0.6) rectangle (2,1.1);}
  715. \only<4>{\draw[fill=c5] (2,0.6) rectangle (3,1.1);}
  716. \only<5>{\draw[fill=c5] (3,0.6) rectangle (4,1.1);}
  717. \only<3>{\draw[fill=c6] (0,0) rectangle (1,0.5);}
  718. \only<4>{\draw[fill=c6] (1,0) rectangle (2,0.5);}
  719. \only<5>{\draw[fill=c6] (2,0) rectangle (3,0.5);}
  720. \only<6>{\draw[fill=c6] (3,0) rectangle (4,0.5);}
  721. \only<6>{\draw[fill=c7] (0,0) rectangle (1,0.5);}
  722. \only<7>{\draw[fill=c7] (1,0) rectangle (2,0.5);}
  723. \only<8>{\draw[fill=c7] (2,0) rectangle (3,0.5);}
  724. \only<9>{\draw[fill=c7] (3,0) rectangle (4,0.5);}
  725. \only<7>{\draw[fill=c8] (0,0) rectangle (1,0.5);}
  726. \only<8>{\draw[fill=c8] (1,0) rectangle (2,0.5);}
  727. \only<9>{\draw[fill=c8] (2,0) rectangle (3,0.5);}
  728. \only<10>{\draw[fill=c8] (3,0) rectangle (4,0.5);}
  729. \only<11>{\draw[fill=c9] (0,0) rectangle (1,0.5);}
  730. \only<12>{\draw[fill=c9] (1,0) rectangle (2,0.5);}
  731. \only<13>{\draw[fill=c9] (2,0) rectangle (3,0.5);}
  732. \only<14>{\draw[fill=c9] (3,0) rectangle (4,0.5);}
  733. \only<15>{\node at (2,0.75) {\Large 14 cycles};}
  734. \only<15>{\node at (2,0.25) {\Large 2\times speedup!};}
  735. \end{tikzpicture}}%
  736. %>>>
  737. %%<<<
  738. %\textcolor{c1}{x\textsuperscript{2} = x * x} \only<1-4>{ $\leftarrow$} \\
  739. %\textcolor{c2}{x\textsuperscript{4} = x\textsuperscript{2} * x\textsuperscript{2}}\only<5-8>{ $\leftarrow$} \\
  740. %\textcolor{c3}{u = a * x + b} \only<2-5>{ $\leftarrow$} \\
  741. %\textcolor{c4}{v = c * x + d} \only<3-6>{ $\leftarrow$} \\
  742. %\textcolor{c5}{w = e * x + f} \only<4-7>{ $\leftarrow$} \\
  743. %\textcolor{c6}{p = g * x + h} \only<6-9>{ $\leftarrow$} \\
  744. %\textcolor{c7}{q = u * x\textsuperscript{2} + v} \only<7-10>{ $\leftarrow$} \\
  745. %\textcolor{c8}{r = w * x\textsuperscript{2} + p} \only<10-13>{ $\leftarrow$} \\
  746. %\textcolor{c9}{s = q * x\textsuperscript{4} + r} \only<14-17>{ $\leftarrow$} \\
  747. %\vspace{0.5em}
  748. %{\bf Pipeline:}
  749. %\vspace{0.1em}
  750. %\resizebox{0.99\textwidth}{!}{\begin{tikzpicture}
  751. % \draw[draw=none] (0,0) rectangle (4,1);
  752. % \only<1-17>{
  753. % \draw[fill=white] (0,0) rectangle (1,1);
  754. % \draw[fill=white] (1,0) rectangle (2,1);
  755. % \draw[fill=white] (2,0) rectangle (3,1);
  756. % \draw[fill=white] (3,0) rectangle (4,1);
  757. % }
  758. % \only<1>{\draw[fill=c1] (0,0) rectangle (1,1);}
  759. % \only<2>{\draw[fill=c1] (1,0) rectangle (2,1);}
  760. % \only<3>{\draw[fill=c1] (2,0) rectangle (3,1);}
  761. % \only<4>{\draw[fill=c1] (3,0) rectangle (4,1);}
  762. % \only<5>{\draw[fill=c2] (0,0) rectangle (1,1);}
  763. % \only<6>{\draw[fill=c2] (1,0) rectangle (2,1);}
  764. % \only<7>{\draw[fill=c2] (2,0) rectangle (3,1);}
  765. % \only<8>{\draw[fill=c2] (3,0) rectangle (4,1);}
  766. % \only<2>{\draw[fill=c3] (0,0) rectangle (1,1);}
  767. % \only<3>{\draw[fill=c3] (1,0) rectangle (2,1);}
  768. % \only<4>{\draw[fill=c3] (2,0) rectangle (3,1);}
  769. % \only<5>{\draw[fill=c3] (3,0) rectangle (4,1);}
  770. %
  771. % \only<3>{\draw[fill=c4] (0,0) rectangle (1,1);}
  772. % \only<4>{\draw[fill=c4] (1,0) rectangle (2,1);}
  773. % \only<5>{\draw[fill=c4] (2,0) rectangle (3,1);}
  774. % \only<6>{\draw[fill=c4] (3,0) rectangle (4,1);}
  775. %
  776. % \only<4>{\draw[fill=c5] (0,0) rectangle (1,1);}
  777. % \only<5>{\draw[fill=c5] (1,0) rectangle (2,1);}
  778. % \only<6>{\draw[fill=c5] (2,0) rectangle (3,1);}
  779. % \only<7>{\draw[fill=c5] (3,0) rectangle (4,1);}
  780. %
  781. % \only<6>{\draw[fill=c6] (0,0) rectangle (1,1);}
  782. % \only<7>{\draw[fill=c6] (1,0) rectangle (2,1);}
  783. % \only<8>{\draw[fill=c6] (2,0) rectangle (3,1);}
  784. % \only<9>{\draw[fill=c6] (3,0) rectangle (4,1);}
  785. % \only<7>{\draw[fill=c7] (0,0) rectangle (1,1);}
  786. % \only<8>{\draw[fill=c7] (1,0) rectangle (2,1);}
  787. % \only<9>{\draw[fill=c7] (2,0) rectangle (3,1);}
  788. % \only<10>{\draw[fill=c7] (3,0) rectangle (4,1);}
  789. % \only<10>{\draw[fill=c8] (0,0) rectangle (1,1);}
  790. % \only<11>{\draw[fill=c8] (1,0) rectangle (2,1);}
  791. % \only<12>{\draw[fill=c8] (2,0) rectangle (3,1);}
  792. % \only<13>{\draw[fill=c8] (3,0) rectangle (4,1);}
  793. % \only<14>{\draw[fill=c9] (0,0) rectangle (1,1);}
  794. % \only<15>{\draw[fill=c9] (1,0) rectangle (2,1);}
  795. % \only<16>{\draw[fill=c9] (2,0) rectangle (3,1);}
  796. % \only<17>{\draw[fill=c9] (3,0) rectangle (4,1);}
  797. % \only<18>{\node at (2,0.75) {\Large 17 cycles};}
  798. % \only<18>{\node at (2,0.25) {\Large 60\% faster!};}
  799. %\end{tikzpicture}}%
  800. %%>>>
  801. \end{columns}
  802. % Helmholtz kernel code example
  803. % sample sort code
  804. % evaluating a polynomial
  805. % what we think happens
  806. % reality!
  807. \end{frame}
  808. %>>>
  809. \begin{frame} \frametitle{Polynomial evaluation: actual performance} %<<<
  810. % perf - show stalled cycles
  811. \end{frame}
  812. %>>>
  813. \begin{frame} \frametitle{Vectorization - GEMM micro-kernel}{} %<<<
  814. % show different ways of vectorizing that don't work
  815. % most languages don't make it easy to specify when it is safe to vectorize (aliasing)
  816. % start with triple loop
  817. % compiler options
  818. % loop unrolling
  819. % __restrict__
  820. %
  821. \end{frame}
  822. %>>>
  823. \begin{frame} \frametitle{Instruction-level parallelism -- summary}{} %<<<
  824. % Use fast operations instead of slow
  825. % Cast all computations in additions, multiplications, bitwise ops (eg. baobzi)
  826. % Avoid expensive ops (div), branches
  827. % vectorization
  828. % data arrangement: AoS vs SoA
  829. % out-of-order execution, pipelining, vectorization:
  830. % - refactor code to expose instruction level parallelism (sometimes even at the cost of extra work)
  831. % batch operations, loop unrolling/fixed-length loops, expose instruction level parallelism
  832. % benefits from fixed-size blocking (compiler can unroll)
  833. % loops have conditionals, so unrolling is difficult
  834. %%%%%%%%%%%%%%% maybe
  835. % unaligned memory accesses
  836. % show penalty from branches
  837. % vector dot product: show data dependency stalls
  838. %%%%%%%%%%%%%%%%%%% not needed
  839. % remove un-necessary operations (pre-allocate memory)
  840. % reduce number of operations (caching)
  841. \end{frame}
  842. %>>>
  843. \begin{frame} \frametitle{Optimized libraries for function evaluationa and vectorization} %<<<
  844. % Fast function evaluation using polynomial evaluation
  845. % baobzi
  846. % sf_benchmarks :
  847. \end{frame}
  848. %>>>