From c8602ecacfac2b9993c5e07c35dda2de94b155d3 Mon Sep 17 00:00:00 2001 From: Luke Kenneth Casson Leighton Date: Tue, 26 Oct 2021 12:04:15 +0100 Subject: [PATCH] opf2021 slides update --- conferences/openpower2021/openpower_2021.tex | 63 ++++++------------- conferences/openpower2021/plonka_dct1.png | Bin 0 -> 13163 bytes 2 files changed, 20 insertions(+), 43 deletions(-) create mode 100644 conferences/openpower2021/plonka_dct1.png diff --git a/conferences/openpower2021/openpower_2021.tex b/conferences/openpower2021/openpower_2021.tex index b6da77501..f76c1c27d 100644 --- a/conferences/openpower2021/openpower_2021.tex +++ b/conferences/openpower2021/openpower_2021.tex @@ -124,7 +124,7 @@ function op\_add(RT, RA, rs2, predr) # add not VADD! \end{frame} \begin{frame}[fragile] -\frametitle{Matrix Multiply Basics} +\frametitle{Matrix Multiply: Basics} \begin{semiverbatim} (a00 a01 a02 x (b00 b01 = @@ -148,31 +148,7 @@ function op\_add(RT, RA, rs2, predr) # add not VADD! \begin{frame}[fragile] -\frametitle{Matrix Multiply Basics} - -\begin{semiverbatim} -(a00 a01 a02 x (b00 b01 = - a10 a11 a12) b10 b11 - b20 b21) - -(a00*b00 + a01*b10 + a02*b20 a00*b01 + a01*b11 + a02*b21 - a10*b00 + a11*b10 + a12*b20 a10*b01 + a11*b11 + a12*b21) - - (b00 b01 x (a00 a01 a02 = - b10 b11 a10 a11 a12) - b20 b21) - -(b00*a00 + b01*a10 b00*a01 + b01*a11 b00*a02 + b01*a12 - b10*a00 + b11*a10 b10*a01 + b11*a11 b10*a02 + b11*a12 - b20*a00 + b21*a10 b20*a01 + b21*a11 b20*a02 + b21*a12) - -\end{semiverbatim} - -\end{frame} - - -\begin{frame}[fragile] -\frametitle{Naive Matrix Multiply with python for-loops} +\frametitle{Matrix Multiply: naive, with python for-loops} \begin{semiverbatim} result = [] # final result @@ -192,7 +168,7 @@ for i in range(len(A)): \end{frame} \begin{frame}[fragile] -\frametitle{Matrix Multiply suitable for Hardware scheduling} +\frametitle{Matrix Multiply: suitable for Hardware scheduling} \begin{semiverbatim} Unsuitable: creates massive Read-After-Write chains @@ -214,19 +190,20 @@ for i in range(len(A)): \end{frame} -\frame{\frametitle{Generalise but Specialise} +\frame{\frametitle{Matrix Multiply: Generalise but Specialise} -\vspace{15pt} +\vspace{8pt} \begin{itemize} \item Why not make a general-purpose nested "Loop" system?\\ + - Other uses (algorithms) beyond Matrix Multiplication\\ - Allow any arbitrary-sized loops\\ - Allow any permutation of nesting\\ - - Allow reversing per-dimension\vspace{8pt} + - Allow reversing per-dimension\vspace{5pt} \item Specialise by making Matrix Multiply "setup" quick/easy\\ - two 32-bit instructions to set up A, B, C sizes\\ - one 64-bit SVP64 FMAC instruction.\\ - - Nothing else needed. Saves on I-Cache\vspace{8pt} + - Nothing else needed. Saves on I-Cache\vspace{5pt} \item Hardware turns out to be near-identical to ZOLC\\ https://opencores.org/projects/hwlu\\ https://libre-soc.org/openpower/sv/remap/\vspace{15pt} @@ -234,7 +211,7 @@ for i in range(len(A)): } \begin{frame}[fragile] -\frametitle{Matrix Multiply unit test / example} +\frametitle{Matrix Multiply: unit test / example} \begin{semiverbatim} 94 def test_sv_remap2(self): @@ -253,28 +230,28 @@ sv.fmadds: uses fp0 as accumulator \end{frame} -\frame{\frametitle{Ehm that's all Folks} +\frame{\frametitle{Matrix Multiply: Ehm that's all Folks} -\vspace{15pt} +\vspace{6pt} \begin{itemize} \item Really is that straightforward: no actual Vector ops\\ - Does not dictate or limit micro-architectural detail\\ - Issues Scalar FMACs into existing back-end hardware\\ - Can use any 4-operand instruction (GF, INT, Bitmanip)\\ - - Any operand width (8/16/32/64), up to 127 ops\vspace{8pt} - \item Specialise by making Matrix Multiply "setup" quick/easy\\ - - two 32-bit instructions to set up A, B, C sizes\\ - - one 64-bit SVP64 FMAC instruction.\\ - - Nothing else needed. Saves on I-Cache\vspace{8pt} - \item Hardware turns out to be near-identical to ZOLC\\ - https://opencores.org/projects/hwlu\\ - https://libre-soc.org/openpower/sv/remap/\vspace{15pt} + - No Power-2 limits. Any operand width (8/16/32/64)\vspace{8pt} + \item Limited to 127 scalar ops and in-place registers. Future?\\ + - https://arxiv.org/abs/2002.10143 CISC-like load-and-inc\\ + - Auto-load/store (tagged) registers, keeps RISC ISA\\ + - Extend to memory-based arbitrary NxN matrix sizes\\ + - Still power-efficient: no I-cache usage during FMAC issue\vspace{8pt} + \item Future can be investigated as part of EUR 22.6m EU Grant\\ + https://libre-soc.org/SEP-210803722-Libre-SOC-8-core/\vspace{15pt} \end{itemize} } -\frame{\frametitle{Summary} +\frame{\frametitle{TODO rewrite Summary} \begin{itemize} \item Goal is to create a mass-volume low-power embedded SoC suitable diff --git a/conferences/openpower2021/plonka_dct1.png b/conferences/openpower2021/plonka_dct1.png new file mode 100644 index 0000000000000000000000000000000000000000..6d41325faadbc4e378d72b60d58bb28cf3d6e873 GIT binary patch literal 13163 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 literal 0 HcmV?d00001 -- 2.30.2