From ae03ebdf1d3a1d5ba477165b9640119d66ba1927 Mon Sep 17 00:00:00 2001 From: Daniel Date: Thu, 8 May 2025 16:32:05 +0200 Subject: [PATCH] implementation: finished re-reading chapter and fixed suboptimal wording --- thesis/chapters/implementation.tex | 29 ++++++++++++----------------- thesis/main.pdf | Bin 919808 -> 919764 bytes 2 files changed, 12 insertions(+), 17 deletions(-) diff --git a/thesis/chapters/implementation.tex b/thesis/chapters/implementation.tex index 903b715..c67b997 100644 --- a/thesis/chapters/implementation.tex +++ b/thesis/chapters/implementation.tex @@ -321,27 +321,22 @@ When the loop encounters a token that represents an index to either the variable However, the first time a variable or parameter is accessed, it must be loaded from global memory. Although registers already exist that hold a pointer to the address of the matrices in global memory, the data is still not accessible. To make it accessible, the index to the value must first be calculated in the same way as it is calculated in the interpreter. Afterwards the value must be loaded into a register with the instruction \verb|ld.global.f32 %reg1, [%reg2]|. Using the first register of the instruction, the data can be accessed. For example, if the variable $x_1$ is accessed several times, all subsequent calls only need to reference this register and do not need to load the data from global memory again. -% -% TODO: Deepl pass -% -In the case where the current token represents an operation, the code for this operation needs to be generated. Many operators have an equivalent on the GPU. For example addition has the \verb|add.f32 %reg1, %reg2, %reg3;| instruction. The instructions for division and square root have an equivalent instruction but only support approximate calculation. While the approximation can be controlled with different options, the fastest option \verb|.approx| has been chosen. Although a slightly slower but more accurate option \verb|.full| exists, it is not fully IEEE 754 compliant and has therefore not been used. +In the case where the current token represents an operation, the code for this operation needs to be generated. Many operators have direct equivalents on the GPU. For example addition has the \verb|add.f32 %reg1, %reg2, %reg3;| instruction. The instructions for division and square root operations have equivalent instruction, but these only support approximate calculations. Although the accuracy can be controlled with different options, the fastest option \verb|.approx| has been selected. While a slightly slower but more accurate option \verb|.full| exists, it is not fully IEEE 754 compliant and has therefore not been used. -However, not all supported operators have a single instruction GPU equivalent. For example the operation $x^y$ has no equivalent and therefore needs to be generated differently. When compiling a kernel with this operation using the Nvidia compiler and the compiler flag \textit{-\,-use\_fast\_math} the following code will be generated: +However, not all supported operators have a single instruction GPU equivalent. For example, the $x^y$ operation does not have an equivalent and must be generated differently. Compiling a kernel containing this operation using the Nvidia compiler and the \textit{-\,-use\_fast\_math} compiler flag will generate the following code: \begin{PTXCode}[numbers=none] lg2.approx.f32 %reg1, %reg2; mul.f32 %reg4, %reg3, %reg1; ex2.approx.f32 %reg5, %reg4; \end{PTXCode} -While this compiler flag trades accuracy for performance, the more accurate version of this operation contains about 100 instructions instead of the above three. Because of this, the more performant version has been chosen to be generated by the transpiler. Similarly, the operations $\log(x)$ and $e^x$ also have no equivalent instruction and are therefore generated following the same principle. +While this compiler flag trades accuracy for performance, the more accurate version of this operation contains about 100 instructions instead of the three above. Therefore, the more performant version was chosen to be generated by the transpiler. Similarly, the operations $\log(x)$ and $e^x$ have no equivalent instruction and are therefore generated using the same principle. -The final register of the generated code, stores the result of the operation once executed. As with the interpreter, this result is either the final value, or an input to another operation. Therefore, this register must be stored in the stack for later use. +The final register of the generated code stores the result of the operation once it has been executed. As with the interpreter, this result is either the final value or an input to another operation. Therefore, this register must be stored on the stack for later use. -Once the main loop has finished, the last element on the stack, holds the register with the result of the evaluation. The value of this register must be stored in the result matrix. As the result matrix is stored in global memory, the code for storing the data is similar to the code responsible for loading the data from global memory. First the location where to store the result must be calculated. Storing the result at this location, is performed with the instruction \verb|st.global.f32 [%reg1], %reg2;|. +Once the main loop has finished, the last element on the stack holds the register with the result of the evaluation. The value of this register must be stored in the result matrix. As the result matrix is stored in global memory, the code for storing the data is similar to the code responsible for loading the data from global memory. First, the location where the result is to be stored must be calculated. Storing the result at this location is performed with the instruction \verb|st.global.f32 [%reg1], %reg2;|. \subsection{GPU Side} -% I am not really happy with this. The length of the paragraph is fine, but the content not so much -% Maybe show a kernel for the expression "x1+p1" or so to show the complexity or something? -On the GPU, the transpiled kernels are simply executed. Because the kernels themselves are very simple, as they contain almost no branching and other overhead work, the GPU does not need to perform a lot of operations. As can be seen in Program \ref{code:ptx_kernel}, the kernel for the expression $x_1 + p_1$ is very straightforward, with only two load operations, the addition and then the storing of the result in the result matrix. In fact, the kernel is a one-to-one mapping of the expression, with the overhead of ensuring only the one thread is executing and loading the variable and parameter. +On the GPU, the transpiled kernels are executed. Given that these kernels are relatively simple, containing minimal branching and overhead, the GPU does not need to perform a lot of operations. As illustrated in Program \ref{code:ptx_kernel}, the kernel for the expression $x_1 + p_1$ is quite straightforward. It involves only two load operations, the addition and the storing of the result in the result matrix. Essentially, the kernel mirrors the expression directly, with the already explained added overhead. \begin{program} \begin{PTXCode} @@ -387,14 +382,14 @@ On the GPU, the transpiled kernels are simply executed. Because the kernels them %\verb|.version| and \verb|.target| -Note that Program \ref{code:ptx_kernel} has been slightly simplified to not include the allocation of the registers. From line five to line ten, the addresses stored in the parameters, are converted from parameter state space into global state space, so that they reference the correct portion of the GPUs memory. It needs to be noted, that this kernel uses 64-bit addresses, which is the reason why throughout the kernel, there are some 64-bit instructions used. Evaluating the expression itself is however entirely performed using the faster 32-bit instructions. +Note that Program \ref{code:ptx_kernel} has been slightly simplified to omit the mandatory directives and the register allocation. From line five to line ten, the addresses stored in the parameters are converted from parameter state space into global state space so that they reference the correct portion of the GPU's memory. It needs to be noted, that this kernel uses 64-bit addresses, which is the reason why some 64-bit instructions are used throughout the kernel. However, the evaluation of the expression itself is performed entirely using the faster 32-bit instructions. -Lines 12 through 17 are responsible to calculate the global thread-ID and ensure that excessive threads are terminated early. Note that in line 16, if the global thread-ID stored in register \verb|%r3| is greater than one, it must terminate early. This is because in this example, only one variable set needs to be evaluated. +Lines 12 through 17 are responsible for calculating the global thread ID and ensuring that excessive threads are terminated early. Note that in line 16, if the global thread ID stored in register \verb|%r3| is greater than one, it must terminate early. This is because only one variable set needs to be evaluated in this example. -The PTX code from line 22 to line 28 is the actual evaluation of the expression, with line 28 performing the calculation $x_1 + p_1$. All other lines, are responsible for loading the values from global memory. The instructions at the lines 22, 23 and 25, 26 are responsible for calculating the offset in bytes to the memory location where the value is stored with respect to the location of the first element. +The PTX code from line 22 to line 28 is the actual evaluation of the expression, with line 28 performing the calculation $x_1 + p_1$. All other lines are responsible for loading the values from global memory. The instructions in lines 22, 23, 25 and 26 are responsible for calculating the offset in bytes to the memory location where the value is stored with respect to the location of the first element. -The constants $4$ and $0$ are introduced due to performance reasons. The number $4$ is the size in bytes of one variable set. As one variable set only stores a single FP32 value in this case, each variable set has a size of four bytes. Similarly, the number $0$ represents the index of the value inside the variable set. More precise, this is the offset in bytes from index to the variable set, which is zero for the first element and four for the second etc. These two constants are calculated during the transpilation process, to minimise the amount of data that needs to be transferred to the GPU. +The constants $4$ and $0$ are introduced for performance reasons. The number $4$ is the size of a variable set in bytes. Since one variable set in this case stores only a single FP32 value, each variable set has a size of four bytes. Similarly, the number $0$ represents the index of the value within the variable set. More precisely, this is the offset in bytes from the index to the variable set, which is zero for the first element, four for the second, and so on. These two constants are calculated during the transpilation process to minimise the amount of data to be transferred to the GPU. -Storing the result in the result matrix is performed from line 31 to 33. The location at which to store the value is calculated in the lines 31 and 32. Line 31 calculates the index inside the result matrix, according to the current variable set stored in register \verb|%rd3|. The constant $0$ is the product of the index of the expression that is evaluated and the number of variable sets and represents the column of the result matrix. Converting this index into bytes and adding it as the offset to the first element of the result matrix, results in the correct memory location to store the result at. +Storing the result in the result matrix is performed from line 31 to 33. The location where the value is to be stored is calculated in lines 31 and 32. Line 31 calculates the index inside the result matrix according to the current variable set stored in register \verb|%rd3|. The constant $0$ is the product of the index of the expression being evaluated and the number of variable sets, and represents the column of the result matrix. Converting this index into bytes and adding it as an offset to the first element of the result matrix gives the correct memory location to store the result at. -This kernel consists mostly of overhead code, as only lines 22 through 33 contribute to calculating the result of the expression with the designated variable and parameter set. However, for larger expressions, the percentage of overhead code drastically shrinks. \ No newline at end of file +This kernel consists mostly of overhead code, as only lines 22 through 33 contribute to calculating the result of the expression with the designated variable and parameter set. However, for larger expressions, the percentage of overhead code shrinks drastically. \ No newline at end of file diff --git a/thesis/main.pdf b/thesis/main.pdf index 5714bc6fe13afb76f32ca3522d985599a34c1f64..c616eb564d9d77754fcfa1a94cfbb83179b8d101 100644 GIT binary patch delta 11566 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 Y)>iXfXH+4gQy}qvMy92eR+T~iAMA?p0RR91