Skip to content

Commit a2132e6

Browse files
committed
Revised up to Section 3.2
1 parent 8cd2a53 commit a2132e6

File tree

1 file changed

+67
-45
lines changed

1 file changed

+67
-45
lines changed

ALP_Tutorial.tex

Lines changed: 67 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -49,66 +49,86 @@ \section{Installation on Linux}\label{sec:installation}
4949
\end{enumerate}
5050
After these steps, you have installed ALP and have made sure its basic functionalities are functional. In the next sections we introduce core ALP/GraphBLAS concepts and walk through a simple example program.
5151

52-
\section{Introduction to ALP Concepts}\label{sec:alp_concepts}
52+
\section{ALP/GraphBLAS}\label{sec:alp_concepts}
5353

54-
ALP exposes a programming model similar to the GraphBLAS standard, using algebraic containers (vectors, matrices, etc.) and algebraic operations on those containers. This section covers the basic data structures, the algebraic structures (semirings) that define how arithmetic is done, and key primitive operations (such as matrix-vector multiply and element-wise operations).
54+
ALP exposes a GraphBLAS interface which separate in three categories: 1) algebraic containers (vectors, matrices, etc.); 2) algebraic structures (binary operators, semrings, etc.); and 3) algebraic operations that take containers and algebraic structures as arguments. This interface was developed in tandem with what became the GraphBLAS C specification, however, is pure C++. All containers, primitives, and algebraic structures are defined in the \texttt{grb} namespace. The ALP user documentation may be useful in course of the exercises. These may be found at: \url{http://albert-jan.yzelman.net/alp/user/}.
5555

56-
\subsection{Vectors and Matrices in ALP}
56+
Let us first bootstrap our tutorial with a simple \emph{Hello World} example:
5757

58-
The primary container types in ALP are \texttt{grb::Vector<T>} and \texttt{grb::Matrix<T>}, defined in the \texttt{grb} namespace. These are templated on a value type \texttt{T}, which is the type of elements stored. Both vectors and matrices can be sparse, meaning they efficiently represent and operate on mostly-zero data by storing only nonzero elements
59-
webspace.science.uu.nl
60-
. For example, one can declare a vector of length 100000 and a 150000$\times$100000 matrix as:
61-
\begin{lstlisting}
62-
grb::Vector<double> x(100000), y(150000);
63-
grb::Matrix<void> A(150000, 100000);
64-
\end{lstlisting}
65-
In this snippet, x and y are vectors of type double. The matrix A is declared with type void, which in ALP means it holds only the pattern of nonzero positions (no numeric values). Typically, one would use a numeric type (e.g. double) for matrix values; a void matrix is a special case where existence of an entry is all that matters (useful for boolean or unweighted graphs).
58+
\begin{lstlisting}[language=c++,morekeywords=constexpr,morekeywords=size_t]
59+
#include <cstddef>
60+
#include <cstring>
6661

67-
By default, new vectors/matrices start empty (with no stored elements). You can query properties like length or dimensions via \texttt{grb::size(vector)} for vector length, \texttt{grb::nrows(matrix)} and \texttt{grb::ncols(matrix)} for matrix dimensions, and \texttt{grb::nnz(container)} for the number of stored nonzero elements.
62+
#include <graphblas.hpp>
6863

69-
\subsubsection{Exercise: Allocating Vectors and Matrices in ALP}
64+
#include <assert.h>
7065

71-
Write a C++ program that uses ALP to allocate two vectors and one matrix as follows:
72-
\begin{itemize}
73-
\item A \texttt{grb::Vector<double>} \texttt{x} of length 100, with initial capacity 100.
74-
\item A \texttt{grb::Vector<double>} \texttt{y} of length 1000, with initial capacity 100.
75-
\item A \texttt{grb::Matrix<double>} \texttt{A} of size $(100 \times 1000)$, with initial capacity 100.
76-
\end{itemize}
77-
Make sure to include the necessary ALP headers, initialize the ALP context, and set the capacities via \texttt{resize}.
66+
constexpr size_t max_fn_size = 255;
67+
typedef char Filename[ max_fn_size ];
7868

79-
\begin{lstlisting}[language=C++,basicstyle=\ttfamily\small, showstringspaces=false]
80-
#include <iostream>
81-
#include <graphblas.hpp>
69+
void hello_world( const Filename &in, int &out ) {
70+
std::cout << "Hello from " << in << std::endl;
71+
out = 0;
72+
}
8273

83-
int main() {
84-
// 1) Initialize ALP (using the sequential reference backend)
85-
grb::init< grb::reference >();
74+
int main( int argc, char ** argv ) {
75+
// get input
76+
Filename fn;
77+
(void) std::strncpy( fn, argv[ 0 ], max_fn_size );
8678

87-
// 2) Allocate vector x of length 100
88-
grb::Vector< double, grb::reference > x( 100 );
89-
grb::resize( x, 100 ); // Set initial capacity of x to 100 nonzeros
79+
// set up output field
80+
int error_code = 100;
9081

91-
// 3) Allocate vector y of length 1000
92-
grb::Vector< double, grb::reference > y( 1000 );
93-
grb::resize( y, 100 ); // Set initial capacity of y to 100 nonzeros
82+
// launch hello world program
83+
grb::Launcher< grb::AUTOMATIC > launcher;
84+
assert( launcher.exec( &hello_world, fn, error_code, true )
85+
== grb::SUCCESS );
9486

95-
// 4) Allocate matrix A of size 100 x 1000
96-
grb::Matrix< double, grb::reference > A( 100, 1000 );
97-
grb::resize( A, 100 ); // Set initial capacity of A to 100 nonzeros
87+
// return with the hello_world error code
88+
return error_code;
89+
}
90+
\end{lstlisting}
9891

99-
// 5) Print the capacities to verify
100-
std::cout << "Capacity of x: " << grb::capacity( x ) << std::endl;
101-
std::cout << "Capacity of y: " << grb::capacity( y ) << std::endl;
102-
std::cout << "Capacity of A: " << grb::capacity( A ) << std::endl;
92+
In this code, we have a very simple \texttt{hello\_world} function that takes its own filename as an input argument, prints a hello statement to \texttt{stdout}, and then returns a zero error code.
93+
ALP uses the concept of a \emph{Launcher} to start ALP programs such as \texttt{hello\_world}, which is examplified in the main function above. This mechanism allows for encapsulation and starting sequences of ALP programs, potentially adaptively based on run-time conditions. The signature of an ALP program always consists of two arguments: the first being program input and the second being program output. The types of both input and output may be any POD type.
10394

104-
// 6) Finalize ALP
105-
grb::finalize();
106-
107-
return 0;
108-
}
95+
Assuming the above is saved as \texttt{alp\_hw.cpp}, it may be compiled and run as follows:
96+
\begin{lstlisting}[language=bash]
97+
$ grbcxx alp_hw.cpp
98+
$ grbrun ./a.out
99+
Info: grb::init (reference) called.
100+
Hello from ./a.out
101+
Info: grb::finalize (reference) called.
102+
$
109103
\end{lstlisting}
110104

111-
When you run this program, ALP will print informational messages about initialization and finalization, and you will see lines reporting each container’s capacity. In particular, you should observe output similar to:
105+
\noindent \textbf{Exercise.} Double-check that you have the expected output from this example, as we will use its framework in the following exercises.
106+
107+
\noindent \textbf{Question.} Why is \texttt{argv[0]} not directly passed as input to \texttt{hello\_world}?
108+
109+
\noindent \textbf{Bonus Question.} Consider the \href{http://albert-jan.yzelman.net/alp/user/classgrb_1_1Launcher.html#af33a2d0ff876594143988613ebaebae7}{programmer reference documentation for the \texttt{grb::Launcher}}, and consider distributed-memory parallel execution in particular. Why is the last argument to \texttt{launcher.exec} \texttt{true}?
110+
111+
112+
\subsection{ALP/GraphBLAS Containers}
113+
114+
The primary ALP/GraphBLAS container types are \texttt{grb::Vector<T>} and \texttt{grb::Matrix<T>}. These are templated on a value type \texttt{T}, the type of elements stored. The type \texttt{T} can be any plain-old-data (POD) type, including \texttt{std::pair} or \texttt{std::complex<T>}. Both vectors and matrices can be sparse, meaning they efficiently represent mostly-zero data by storing only nonzero elements. For example, one can declare a vector of length $100\ 000$ and a $150\ 000\times100\ 000$ matrix as:
115+
\begin{lstlisting}
116+
grb::Vector<double> x(100000), y(150000);
117+
grb::Matrix<void> A(150000, 100000);
118+
\end{lstlisting}
119+
In this snippet, \texttt{x} and \texttt{y} are vectors of type \texttt{double}. The matrix \texttt{A} is declared with type \texttt{void}, which signifies it only holds the pattern of nonzero positions and no numeric values. Perhaps more commonly, one would use a numeric type (e.g. \texttt{double}) for holding matrix nonzeroes. A \texttt{void} matrix as in the above example is useful for cases where existence of an entry is all that matters, as e.g.\ for storing Boolean matrices or unweighted graphs.
120+
121+
By default, newly instantiated vectors or matrices are empty, meaning they store no elements. You can query properties like length or dimensions via \texttt{grb::size(vector)} for vector length or \texttt{grb::nrows(matrix)} and \texttt{grb::ncols(matrix)} for matrix dimensions. The number of elements present within a container may be retrieved via \texttt{grb::nnz(container)}. Containers have a maximum capacity on the number of elements they may store; the capacity may be retrieved via \texttt{grb::capacity(container)} and on construction of a container is set to the maximum of its dimensions. For example, the initial capacity of \texttt{x} in the above is $100\ 000$, while that of \texttt{A} is $150\ 000$. The size of a container once initialised is fixed, while the capacity may increase during the lifetime of a container.
122+
123+
\noindent \textbf{Exercise.} Allocate vectors and matrices in ALP as follows:
124+
\begin{itemize}
125+
\item A \texttt{grb::Vector<double>} \texttt{x} of length 100, with initial capacity 100.
126+
\item A \texttt{grb::Vector<double>} \texttt{y} of length 1\ 000, with initial capacity 200.
127+
\item A \texttt{grb::Matrix<double>} \texttt{A} of size $(100 \times 1\ 000)$, with initial capacity 100.
128+
\end{itemize}
129+
You may start from a copy of \texttt{alp\_hw.cpp}. Employ \texttt{grb::capacity} to print out the capacities of each of the containers. \textbf{Hint:} refer to the user documentation on how to override the default capacities.
130+
131+
If done correctly, you should observe output similar to:
112132

113133
\begin{lstlisting} [language=bash, basicstyle=\ttfamily\small, showstringspaces=false]
114134
Info: grb::init (reference) called.
@@ -118,6 +138,8 @@ \subsubsection{Exercise: Allocating Vectors and Matrices in ALP}
118138
Info: grb::finalize (reference) called.
119139
\end{lstlisting}
120140

141+
\noindent \textbf{Question.} Is overriding the default capacity necessary for all of \texttt{x, y, A}?
142+
121143
\subsection{Semirings and Algebraic Operations}
122144

123145
A key feature of GraphBLAS (and ALP) is that operations are defined over semirings rather than just the conventional arithmetic operations. A semiring consists of a pair of operations (an “addition” and a “multiplication”) along with their identity elements, which generalize the standard arithmetic (+ and $\times$). GraphBLAS allows using different semirings to, for example, perform computations like shortest paths or logical operations by substituting the plus or times operations with min, max, logical OR/AND, etc. In GraphBLAS, matrix multiplication is defined in terms of a semiring: the “add” operation is used to accumulate results, and the “multiply” operation is used when combining elements.

0 commit comments

Comments
 (0)