![]() |
MAGMA
2.7.1
Matrix Algebra for GPU and Multicore Architectures
|
The following coding style should be followed in all MAGMA code. Consistency is important, and clarity of code is paramount. There are rare occasions to ignore a particular guideline, when following it would make the code less readable. The overriding goal is to make code easy-to-read and maintainable. This guide is based on the PLASMA coding style guide, though slightly different.
ISO C++ standard: CPU code should conform to ISO C++ (C++11
) or ISO C (C99
). GPU code should conform to the CUDA or OpenCL specs. One way to check for compliance is to use the following commands:
g++ -std=c++11 -Wall -pedantic -c magma.cpp gcc -std=c99 -Wall -pedantic -c magma.c
This can be done by setting CFLAGS and CXXFLAGS appropriately in make.inc. MAGMA code needs to be portable and work on Unix, MacOS, and Windows. Most MAGMA code is compiled as C++, but uses essentially C style conventions. For example, all externally visible functions are declared extern "C"
and C-style malloc routines are used, instead of the C++ new
operator.
Whitespace Separators: There should be a space between a C language keyword (if, for, while
) and the left parenthesis, and a space before the left curly brace. There should be a space after the start of a comment (// foo
). There should not be space between a function name and the left parenthesis.
There should be a space before and after boolean operators (<, <=, >, >=, ==, !=
) and assignment operators (=, +=, -=, *=, /=
), except when declaring a variable or initializing a loop variable. There should not be space between increment operators (++, --
) and the variable. Space may be used around other operators (+, -,
etc.) to aid readability.
Semi-colons are not preceded by a space. Inside for loop statement, semi-colons are followed by a space, e.g., for (i=0; i < n; ++i). Similarly, commas are not preceded by a space, and are followed by a space. Occasionally, additional spaces can be used after the comma to line up items on consecutive lines for better readability.
Indentation and Braces: Every function, if block, and loop should be indented by four spaces. For functions, the opening and closing braces are on lines by themselves, in the first column. For control flow (if, else, for, while
), the left curly brace follows the control flow statement on the same line. There is no newline between the control flow statement and the block enclosed by curly braces. The closing curly brace is on a new line right after the end of the enclosed block.
Even when the body of a block is only one line, it should be on a separate line from the control flow statement, and it is preferred to enclose it with curly braces to avoid errors when adding code (goto fail; goto fail;
). Especially, loops and if statements containing more than one line of text should have curly braces, regardless of the number of C statements.
int foo[4][4]
). We use macros to implement 2D matrices. The macro returns a pointer to the element, not the element itself, unlike A[i][j]
. For CUDA and Xeon Phi, dA(i,j)
yields the pointer to element i,j. In OpenCL, dA(i,j)
yields two values: the cl_mem object dA, and the offset to element i,j. This significantly improves the ease of writing code, readability, and porting to platforms such as OpenCL.Documentation: Each function should be documented using Doxygen, using a C-style comment block immediately before the function. Generally follow the traditional LAPACK documentation style, with added Doxygen markup.
A Purpose section gives an overall description of the routine.
An Arguments section specifies each argument — spelled and capitalized exactly as in the C code — with its type, dimensions, description, and valid values (e.g., n >= 0).
Each function should be placed in a group using @
ingroup
, which groups routines by the related driver routine (e.g., zgetrf
, zgetri
, zgetf2
are all in one of the magma_zgesv
groups), and whether it is a driver, computational, or auxiliary routine. There are also groups for BLAS and auxiliary routines. See docs/doxygen-modules.h
for a list of groups (modules).
After compiling documentation (cd docs ; make
), check docs/output_err
for missing parameters or other issues.
magmablas_zlacpy
) should be documented with Doxygen, as above. The low-level, internal CUDA/OpenCL kernel itself (e.g., zlacpy_device_full
) should have a short paragraph describing how the matrix or computation is divided into blocks, and what each thread does. This tremendously increases the readability and maintainability of GPU device code, which is inherently difficult to understand. For instance:Tabs: Tab characters should not be used. Tabs should always be emulated by four spaces, a feature available in almost any text editor.
For vim, sample ~/.vimrc file:
" see http://stackoverflow.com/questions/19835905 set shiftwidth=4 set softtabstop=4 set expandtab set shiftround
For emacs, sample ~/.emacs file:
; see http://www.emacswiki.org/emacs/NoTabs ; see http://www.emacswiki.org/emacs/IndentingC (setq-default indent-tabs-mode nil) (setq c-default-style "k&r" c-basic-offset 4)
for
statement itself.printf
calls to print a multi-line message. One printf
can be used with multiple strings:magma_zlapack.h
).magma_
or magmablas_
, and are all lowercase (e.g., magma_zgetrf
).MagmaNoTrans
), and are CamelCase.MAGMA_Z_ADD
), and are all uppercase.zgetrf.cpp
contains magma_zgetrf()
. External header filenames should be prefixed with magma_
or magmablas_
; they are in the include
directory.Variables: follow general math typesetting rules: matrices are uppercase (A, B, C
), vectors are lowercase (x, y, z
), matrix sizes are lowercase (m, n, k
), loop indices are lowercase (i, j, k
), scalars are often Greek (alpha, beta
).
Variables on the CPU should follow LAPACK names.
Variables on the GPU are similar but have "d" prepended. The corresponding leading dimension likewise has an added "d": dA
and ldda
, dB
and lddb
, etc.