SuperLU Users' Guide and Overview
SuperLU Users' Guide and Overview
September 1999
∗
The work was supported by Director, Office of Science, Office of Advanced Scientic Computing Research
of the U.S. Department of Energy under Contract No. DE-AC02-05CH11231. Additional support was
provided by the U.S. Dept. of Energy (DOE), Office of Science, Advanced Scientific Computing Research
(and Basic Energy Sciences/Biological and Environmental Research/High Energy Physics/Fusion Energy
Sciences/Nuclear Physics), through the Scientific Discovery through Advanced Computing (SciDAC) pro-
gram.
†
Lawrence Berkeley National Laboratory, MS 50F-1650, 1 Cyclotron Rd, Berkeley, CA 94720.
(xsli@[Link]).
‡
Computer Science Division, University of California, Berkeley, CA 94720. (demmel@[Link]).
The research of Demmel and Li was supported in part by NSF grant ASC–9313958, DOE grant DE–FG03–
94ER25219, UT Subcontract No. ORA4466 from ARPA Contract No. DAAL03–91–C0047, DOE grant DE–
FG03–94ER25206, and NSF Infrastructure grants CDA–8722788 and CDA–9401156.
§
Department of Computer Science, University of California, Santa Barbara, CA 93106.
(gilbert@[Link]). The research of this author was supported in part by the Institute for Mathematics
and Its Applications at the University of Minnesota and in part by DARPA Contract No. DABT63-95-C0087.
Copyright c 1994-1997 by Xerox Corporation. All rights reserved.
¶
INRIA Saclay-Ile de France, Laboratoire de Recherche en Informatique, Universite Paris-Sud 11.
([Link]@[Link])
k
Computational Science and Engineering Division, Georgia Institute of Technology, Atlanta.
(piyush3@[Link]). The research of this author was supported in part by the National Science Founda-
tion CAREER award number 0953100 and DOE X-Stack 1.0 under DE-FC02-10ER26006/DE-SC0004915
(PI: Richard Vuduc).
∗∗
Computational Research Division, Lawrence Berkeley National Laboratory, MS 50F-1650, 1 Cyclotron
Rd, Berkeley, CA 94720. (myshao@[Link]).
††
Innovative Computing Laboratory, Department of Electrical Engineering and Computer Science, The
University of Tennessee. ([Link]@[Link]). The research of this author was supported in part by
the Director, Office of Advanced Scientific Computing Research of the U.S. Department of Energy under
Contract No. D-AC02-05CH11231.
Contents
1 Introduction 4
1.1 Purpose of SuperLU . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
1.2 Overall Algorithm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
1.3 What the three libraries have in common . . . . . . . . . . . . . . . . . . . . . . . . 6
1.3.1 Input and Output Data Formats . . . . . . . . . . . . . . . . . . . . . . . . . 6
1.3.2 Tuning Parameters for BLAS . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
1.3.3 Performance Statistics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
1.3.4 Error Handling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
1.3.5 Ordering the Columns of A for Sparse Factors . . . . . . . . . . . . . . . . . 8
1.3.6 Iterative Refinement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
1.3.7 Error Bounds . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
1.3.8 Solving a Sequence of Related Linear Systems . . . . . . . . . . . . . . . . . . 10
1.3.9 Interfacing to other languages . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
1.4 How the three libraries differ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
1.4.1 Input and Output Data Formats . . . . . . . . . . . . . . . . . . . . . . . . . 11
1.4.2 Parallelism . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
1.4.3 Pivoting Strategies for Stability . . . . . . . . . . . . . . . . . . . . . . . . . . 11
1.4.4 Memory Management . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
1.4.5 Interfacing to other languages . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
1.5 Performance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
1.6 Software Status and Availability . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
1.7 Acknowledgement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
1
2.9.1 Driver routines . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
2.9.2 Computational routines . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
2.9.3 Utility routines . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
2.10 Matlab interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
2.11 Installation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
2.11.1 File structure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
2.11.2 Testing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
2.11.3 Performance-tuning parameters . . . . . . . . . . . . . . . . . . . . . . . . . . 36
2.12 Example programs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
2.13 Calling from Fortran . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
2
4.10 Example programs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
4.11 Fortran 90 Interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
4.11.1 Callable functions in the Fortran 90 module file spuerlu mod.f90 . . . . . . . . 74
4.11.2 C wrapper functions callable by Fortran in file spuerlu c2f wrap.c . . . . . . . 75
3
Chapter 1
Introduction
• Sequential SuperLU is designed for sequential processors with one or more layers of memory
hierarchy (caches) [6].
• Distributed SuperLU (SuperLU DIST) is designed for distributed memory parallel pro-
cessors, using MPI [29] for interprocess communication. It can effectively use hundreds of
parallel processors on sufficiently large matrices [25, 26].
Table 1.1 summarizes the current status of the software. All the routines are implemented in
C, with parallel extensions using Pthreads or OpenMP for shared-memory programming, or MPI
for distributed-memory programming. We provide Fortran interface for all three libraries.
The rest of the Introduction is organized as follows. Section 1.2 describes the high-level algo-
rithm used by all three libraries, pointing out some common features and differences. Section 1.3
describes the detailed algorithms, data structures, and interface issues common to all three routines.
Section 1.4 describes how the three routines differ, emphasizing the differences that most affect the
user. Section 1.6 describes the software status, including planned developments, bug reporting, and
licensing.
4
Sequential SuperLU SuperLU MT SuperLU DIST
Platform serial shared-memory distributed-memory
Language C C + Pthreads C + MPI
(with Fortran interface) (or OpenMP)
Data type real/complex real/complex real/complex
single/double single/double double
2. Solve AX = B by evaluating X = A−1 B = (Dr−1 Pr−1 LU Pc−1 Dc−1 )−1 B = Dc (Pc (U −1 (L−1 (Pr (Dr B))))).
This is done efficiently by multiplying from right to left in the last expression: Scale the rows
of B by Dr . Multiplying Pr B means permuting the rows of Dr B. Multiplying L−1 (Pr Dr B)
means solving nrhs triangular systems of equations with matrix L by substitution. Similarly,
multiplying U −1 (L−1 (Pr Dr B)) means solving triangular systems with U .
In addition to complete factorization, we also have limited support for incomplete factorization
(ILU) preconditioner.
The simplest implementation, used by the “simple driver” routines in SuperLU and SuperLU MT,
is as follows:
Simple Driver Algorithm
1. Choose Pc to order the columns of A to increase the sparsity of the computed L and U factors,
and hopefully increase parallelism (for SuperLU MT).
2. Compute the LU factorization of APc . SuperLU and SuperLU MT can perform dynamic
pivoting with row interchanges for numerical stability, computing Pr , L and U at the same
time.
The simple driver subroutines for double precision real data are called dgssv and pdgssv for
SuperLU and SuperLU MT, respectively. The letter d in the subroutine names means double
precision real; other options are s for single precision real, c for single precision complex, and z for
double precision complex. The subroutine naming scheme is analogous to the one used in LAPACK
[1]. SuperLU DIST does not include this simple driver.
5
There is also an “expert driver” routine that can provide more accurate solutions, compute
error bounds, and solve a sequence of related linear systems more economically. It is available in
all three libraries.
Expert Driver Algorithm
1. Equilibrate the matrix A, i.e. compute diagonal matrices Dr and Dc so that  = Dr ADc is
“better conditioned” than A, i.e. Â−1 is less sensitive to perturbations in  than A−1 is to
perturbations in A.
2. Preorder the rows of  (SuperLU DIST only), i.e. replace  by Pr  where Pr is a permutation
matrix. We call this step “static pivoting”, and it is only done in the distributed-mmemory
algorithm.
3. Order the columns of  to increase the sparsity of the computed L and U factors, and
hopefully increase parallelism (for SuperLU MT and SuperLU DIST). In other words, replace
 by ÂPcT in SuperLU and SuperLU MT, or replace  by Pc ÂPcT in SuperLU DIST, where
Pc is a permutation matrix.
4. Compute the LU factorization of Â. SuperLU and SuperLU MT can perform dynamic pivot-
ing with row interchanges for numerical stability. In contrast, SuperLU DIST uses the order
computed by the preordering step but replaces tiny pivots by larger values for stability.
5. Solve the system using the computed triangular factors.
6. Iteratively refine the solution, again using the computed triangular factors. This is equivalent
to Newton’s method.
7. Compute error bounds. Both forward and backward error bounds are computed, as described
below.
The expert driver subroutines for double precision real data are called dgssvx, pdgssvx and
pdgssvx for SuperLU, SuperLU MT and SuperLU DIST, respectively. The driver routines are
composed of several lower level computational routines for computing permutations, computing LU
factorization, solving triangular systems, and so on. For large matrices, the LU factorization steps
takes most of the time, although choosing Pc to order the columns can also be time-consuming.
6
1.3.2 Tuning Parameters for BLAS
All three libraries depend on having high performance BLAS (Basic Linear Algebra Subroutine)
libraries [22, 9, 8] in order to get high performance. In particular, they depend on matrix-vector
multiplication or matrix-matrix multiplication of relatively small dense matrices. The sizes of these
small dense matrices can be tuned to match the “sweet spot” of the BLAS by setting certain
tuning parameters described in section 2.11.3 for SuperLU, in section 3.5.2 for SuperLU MT, and
in section 4.9.2 for SuperLU DIST.
(In addition, SuperLU MT and SuperLU DIST let one control the number of parallel processes
to be used, as described in section 1.4.)
typedef struct {
int *panel_histo; /* histogram of panel size distribution */
double *utime; /* time spent in various phases */
float *ops; /* floating-point operations at various phases */
int TinyPivots; /* number of tiny pivots */
int RefineSteps; /* number of iterative refinement steps */
} SuperLUStat_t;
For both SuperLU and SuperLU MT, there is only one copy of these statistics variable. But
for SuperLU DIST, each process keeps a local copy of this variable, and records its local statistics.
We need to use MPI reduction routines to find any global information, such as the sum of the
floating-point operation count on all processes.
Before the computation, routine StatInit() should be called to malloc storage and perform
initialization for the fields panel histo, utime, and ops. The algorithmic phases are defined by the
enumeration type PhaseType in SRC/util.h. In the end, routine StatFree() should be called to
free storage of the above statistics fields. After deallocation, the statistics are no longer accessible.
Therefore, users should extract the information they need before calling StatFree(), which can be
accomplished by calling (P)StatPrint().
An inquiry function dQuerySpace() is provided to compute memory usage statistics. This
routine should be called after the LU factorization. It calculates the storage requirement based on
the size of the L and U data structures and working arrays.
7
has an illegal value. The program returns immediately from the routine, with a negative value of
INFO.
• Natural ordering,
COLAMD is designed particularly for unsymmetric matrices when partial pivoting is needed,
and does not require explicit formation of AT A. It usually gives comparable orderings as MMD on
AT A, and is faster.
The orderings based on graph partitioning heuristics are also popular, as exemplified in the
MeTiS package [20]. The user can simply input this ordering in the permutation vector for Pc . Note
that many graph partitioning algorithms are designed for symmetric matrices. The user may still
apply them to the structures of AT A or AT + A. Our routines getata() and at plus a() in the
file get perm c.c can be used to form AT A or AT + A.
8
1.3.6 Iterative Refinement
Step 6 of the expert driver algorithm, iterative refinement, serves to increase accuracy of the
computed solution. Given the initial approximate solution x from step 5, the algorithm for step 6
is as follows (where x and b are single columns of X and B, respectively):
Compute residual r = Ax − b
While residual too large
Solve Ad = r for correction d
Update solution x = x − d
Update residual r = Ax − b
end while
If r and then d were computed exactly, the updated solution x − d would be the exact solution.
Roundoff prevents immediate convergence.
The criterion “residual too large” in the iterative refinement algorithm above is essentially that
exceeds the machine roundoff level, or is continuing to decrease quickly enough. Here si is the scale
factor X
si = (|A| · |x| + |b|)i = |Aij | · |xj | + |bi |
j
In this expression |A| is the n-by-n matrix with entries |A|ij = |Aij |, |b| and |x| are similarly
column vectors of absolute entries of b and x, respectively, and |A| · |x| is conventional matrix-
vector multiplication.
The purpose of this stopping criterion is explained in the next section.
9
Here kxk∞ ≡ maxi |xi |. Thus, if F ERR = 10−6 then each component of x has an error bounded
by about 10−6 times the largest component of x. The algorithm used to compute F ERR is an
approximation; see [2, 19] for a discussion. Generally F ERR is accurate to within a factor of 10
or better, which is adequate to say how many digits of the large entries of x are correct.
(SuperLU DIST’s algorithm for F ERR is slightly less reliable [26].)
1. Factor from scratch. No previous information is used. If one were solving just one linear
system, or a sequence of unrelated linear systems, this is the option to use.
2. Reuse Pc , the column permutation. The user may save the column permutation and reuse
it. This is most useful when A(2) has the same sparsity structure as A(1) , but not necessarily
the same (or similar) numerical entries. Reusing Pc saves the sometimes quite expensive
operation of computing it.
3. Reuse Pc , Pr and data structures allocated for L and U . If Pr and Pc do not change, then
the work of building the data structures associated with L and U (including the elimination
tree [16]) can be avoided. This is most useful when A(2) has the same sparsity structure and
similar numerical entries as A(1) . When the numerical entries are not similar, one can still use
this option, but at a higher risk of numerical instability (BERR will always report whether or
not the solution was computed stably, so one cannot get an unstable answer without warning).
Because of the different ways L and U are computed and stored in the three libraries, these 4
options are specified slightly differently; see Chapters 2 through 4 for details.
10
1.4 How the three libraries differ
1.4.1 Input and Output Data Formats
All Sequential SuperLU and SuperLU MT routines are available in single and double precision (real
or complex), but SuperLU DIST routines are available only in double precision (real or complex).
L and U are stored in different formats in the three libraries:
• L and U in SuperLU MT. Because of parallelism, the columns of L and U may not be
computed in consecutive order, so they may be allocated and stored out of order. This means
we use the “column-supernodal-permuted” format SCPformat for L and “column-permuted”
format NCPformat for U . See section 3.2 for details.
• L and U in SuperLU DIST. Now L and U are distributed across multiple processors. As
described in detail in Sections 4.3 and 4.4, we use a 2D block-cyclic format, which has been
used for dense matrices in libraries like ScaLAPACK [4]. But for sparse matrices, the blocks
are no longer identical in size, and vary depending on the sparsity structure of L and U . The
detailed storage format is discussed in section 4.3 and illustrated in Figure 4.1.
1.4.2 Parallelism
Sequential SuperLU has no explicit parallelism. Some parallelism may still be exploited on an
SMP by using a multithreaded BLAS library if available. But it is likely to be more effective to
use SuperLU MT on an SMP, described next.
SuperLU MT lets the user choose the number of parallel threads to use. The mechanism varies
from platform to platform and is described in section 3.7.
SuperLU DIST not only lets the user specify the number of processors, but how they are
arranged into a 2D grid. Furthermore, MPI permits any subset of the processors allocated to the
user may be used for SuperLU DIST, not just consecutively numbered processors (say 0 through
P-1). See section 4.4 for details.
11
guarantees that the pivots on the diagonal will be chosen, unless they are zero. The error bound
BERR measure how much stability is actually lost.
Threshold pivoting turns out to be hard to parallelize on distributed memory machines, because
of the fine-grain communication and dynamic data structures required. So SuperLU DIST uses a
new scheme called static pivoting instead. In static pivoting the pivot order (Pr ) is chosen before
numerical factorization, using a weighted perfect matching algorithm [10], and kept fixed during
factorization. Since both row and column orders (Pr and Pc ) are fixed before numerical factoriza-
tion, we can extensively optimize the data layout, load balance, and communication schedule. The
price is a higher risk of numeric instability, which is mitigated by diagonal scaling, setting very
tiny pivots to larger values, and iterative refinement [26]. Again, error bound BERR measure how
much stability is actually lost.
1.5 Performance
SuperLU library incorporates a number of novel algorithmic ideas developed recently. These al-
gorithms also exploit the features of modern computer architectures, in particular, the multi-level
cache organization and parallelism. We have conducted extensive experiments on various plat-
forms, with a large collection of test matrices. The Sequential SuperLU achieved up to 40% of the
theoretical floating-point rate on a number of processors, see [6, 23]. The megaflop rate usually
increases with increasing ratio of floating-point operations count over the number of nonzeros in the
L and U factors. The parallel LU factorization in SuperLU MT demonstrated 5–10 fold speedups
on a range of commercially popular SMPs, and up to 2.5 Gigaflops factorization rate, see [7, 23].
12
The parallel LU factorization in SuperLU DIST achieved up to 100 fold speedup on a 512-processor
Cray T3E, and 10.2 Gigaflops factorization rate, see [25].
Copyright (c) 2003, The Regents of the University of California, through Lawrence
Berkeley National Laboratory (subject to receipt of any required approvals from U.S.
Dept. of Energy)
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are
permitted provided that the following conditions are met:
(1) Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer. (2) Redistributions in binary form must
reproduce the above copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the distribution. (3) Neither
the name of Lawrence Berkeley National Laboratory, U.S. Dept. of Energy nor the
names of its contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CON-
TRIBUTORS ”AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, IN-
CLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER-
CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LI-
ABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PRO-
CUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSI-
BILITY OF SUCH DAMAGE.
13
Permission is hereby granted to use or copy this program for any purpose, provided
the above notices are retained on all copies. Permission to modify the code and to
distribute modified code is granted, provided the above notices are retained, and a
notice that the code was modified is included with the above copyright notice.
2. The MC64 routine (only used in SuperLU DIST) carries the following notice:
COPYRIGHT (c) 1999 Council for the Central Laboratory of the Research Coun-
cils. All rights reserved. PACKAGE MC64A/AD AUTHORS Iain Duff ([Link]@[Link])
and Jacko Koster (jak@[Link]) LAST UPDATE 20/09/99
*** Conditions on external use ***
The user shall acknowledge the contribution of this package in any publication of
material dependent upon the use of the package. The user shall use reasonable
endeavours to notify the authors of the package of this publication.
The user can modify this code but, at no time shall the right or title to all or any
part of this package pass to the user. The user shall make available free of charge
to the authors for any purpose all information relating to any alteration or addition
made to this package for the purposes of extending the capabilities or enhancing
the performance of this package.
The user shall not pass this code directly to a third party without the express prior
consent of the authors. Users wanting to licence their own copy of these routines
should send email to hsl@[Link]
None of the comments from the Copyright notice up to and including this one shall
be removed or altered in any way.
[Link]
[Link]
In the future, we will add more functionality in the software, such as sequential and parallel in-
complete LU factorizations, as well as parallel symbolic and ordering algorithms for SuperLU DIST;
these latter routines would replace MC64 and have no restrictions on external use.
All bugs reports and queries can be e-mailed to xsli@[Link] and demmel@[Link].
1.7 Acknowledgement
With great gratitude, we acknowledge Stan Eisenstat and Joesph Liu for their significant contri-
butions to the development of Sequential SuperLU. Meiyue Shao helped the development of the
incomplete factorization ILU routines in sequential SuperLU.
We would like to thank Jinqchong Teo for helping generate the code in Sequential SuperLU to
work with four floating-point data types, and Daniel Schreiber for doing this with SuperLU MT.
Yu Wang and William F. Mitchell developed the Fortran 90 interface for SuperLU DIST. Laura
Grigori developed the parallel symbolic factorization code for SuperLU DIST.
We thank Tim Davis for his contribution of some subroutines related to column ordering and
suggestions on improving the routines’ interfaces. We thank Ed Rothberg of Silicon Graphics for
14
discussions and providing us access to the SGI Power Challenge during the SuperLU MT develop-
ment.
We acknowledge the following organizations that provided the computer resources during our
code development: NERSC at Lawrence Berkeley National Laboratory, Livermore Computing at
Lawrence Livermore National Laboratory, NCSA at University of Illinois at Urbana-Champaign,
Silicon Graphics, and Xerox Palo Alto Research Center. We thank UC Berkeley and NSF Infras-
tructure grant CDA-9401156 for providing Berkeley NOW.
15
Chapter 2
16
s u u 19.00 21.00 21.00
l u 0.63 21.00 −13.26 −13.26
l p 0.57 23.58 7.58
e u 5.00 21.00
l l r 0.63 0.57 −0.24 −0.77 34.20
#include "slu_ddefs.h"
17
int *perm_c; /* column permutation vector */
int nrhs, info, i, m, n, nnz, permc_spec;
superlu_options_t options;
SuperLUStat_t stat;
/* Initialize matrix A. */
m = n = 5;
nnz = 12;
if ( !(a = doubleMalloc(nnz)) ) ABORT("Malloc fails for a[].");
if ( !(asub = intMalloc(nnz)) ) ABORT("Malloc fails for asub[].");
if ( !(xa = intMalloc(n+1)) ) ABORT("Malloc fails for xa[].");
s = 19.0; u = 21.0; p = 16.0; e = 5.0; r = 18.0; l = 12.0;
a[0] = s; a[1] = l; a[2] = l; a[3] = u; a[4] = l; a[5] = l;
a[6] = u; a[7] = p; a[8] = u; a[9] = e; a[10]= u; a[11]= r;
asub[0] = 0; asub[1] = 1; asub[2] = 4; asub[3] = 1;
asub[4] = 2; asub[5] = 4; asub[6] = 0; asub[7] = 2;
asub[8] = 0; asub[9] = 3; asub[10]= 3; asub[11]= 4;
xa[0] = 0; xa[1] = 3; xa[2] = 6; xa[3] = 8; xa[4] = 10; xa[5] = 12;
dPrint_CompCol_Matrix("A", &A);
dPrint_CompCol_Matrix("U", &U);
dPrint_SuperNode_Matrix("L", &L);
print_int_vec("\nperm_r", m, perm_r);
18
/* De-allocate storage */
SUPERLU_FREE (rhs);
SUPERLU_FREE (perm_r);
SUPERLU_FREE (perm_c);
Destroy_CompCol_Matrix(&A);
Destroy_SuperMatrix_Store(&B);
Destroy_SuperNode_Matrix(&L);
Destroy_CompCol_Matrix(&U);
StatFree(&stat);
}
A L U B X
Stype SLU NC or SLU NR SLU SC SLU NC SLU DN SLU DN
Dtype1 any any any any any
Mtype SLU GE SLU TRLU SLU TRU SLU GE SLU GE
In what follows, we illustrate the storage schemes defined by Stype. Following C’s convention,
all array indices and locations below are zero-based.
• A may have storage type SLU NC or SLU NR. The SLU NC format is the same as the Harwell-
Boeing sparse matrix format [12], that is, the compressed column storage.
typedef struct {
int nnz; /* number of nonzeros in the matrix */
void *nzval; /* array of nonzero values packed by column */
int *rowind; /* array of row indices of the nonzeros */
int *colptr; /* colptr[j] stores the location in nzval[] and rowind[]
which starts column j. It has ncol+1 entries,
1
Dtype can be one of SLU S, SLU D, SLU C or SLU Z.
19
typedef struct {
Stype_t Stype; /* Storage type: indicates the storage format of *Store. */
Dtype_t Dtype; /* Data type. */
Mtype_t Mtype; /* Mathematical type */
int nrow; /* number of rows */
int ncol; /* number of columns */
void *Store; /* pointer to the actual storage of the matrix */
} SuperMatrix;
typedef enum {
SLU_NC, /* column-wise, not supernodal */
SLU_NR, /* row-wise, not supernodal */
SLU_SC, /* column-wise, supernodal */
SLU_SR, /* row-wise, supernodal */
SLU_NCP, /* column-wise, not supernodal, permuted by columns
(After column permutation, the consecutive columns of
nonzeros may not be stored contiguously. */
SLU_DN, /* Fortran style column-wise storage for dense matrix */
SLU_NR_loc /* distributed compressed row format */
} Stype_t;
typedef enum {
SLU_S, /* single */
SLU_D, /* double */
SLU_C, /* single-complex */
SLU_Z /* double-complex */
} Dtype_t;
typedef enum {
SLU_GE, /* general */
SLU_TRLU, /* lower triangular, unit diagonal */
SLU_TRUU, /* upper triangular, unit diagonal */
SLU_TRL, /* lower triangular */
SLU_TRU, /* upper triangular */
SLU_SYL, /* symmetric, store lower half */
SLU_SYU, /* symmetric, store upper half */
SLU_HEL, /* Hermitian, store lower half */
SLU_HEU /* Hermitian, store upper half */
} Mtype_t;
20
and colptr[ncol] = nnz. */
} NCformat;
typedef struct {
int nnz; /* number of nonzeros in the matrix */
void *nzval; /* array of nonzero values packed by row */
int *colind; /* array of column indices of the nonzeros */
int *rowptr; /* rowptr[j] stores the location in nzval[] and colind[]
which starts row j. It has nrow+1 entries,
and rowptr[nrow] = nnz. */
} NRformat;
The factorization and solve routines in SuperLU are designed to handle column-wise storage
only. If the input matrix A is in row-oriented storage, i.e., in SLU NR format, then the driver
routines (dgssv() and dgssvx()) actually perform the LU decomposition on AT , which is
column-wise, and solve the system using the LT and U T factors. The data structures holding
L and U on output are different (swapped) from the data structures you get from column-wise
input. For more detailed descriptions about this process, please refer to the leading comments
of the routines dgssv() and dgssvx().
Alternatively, the users may call a utility routine dCompRow to CompCol() to convert the
input matrix in SLU NR format to another matrix in SLU NC format, before calling SuperLU.
The definition of this routine is
This conversion takes time proportional to the number of nonzeros in A. However, it requires
storage for a separate copy of matrix A.
• L is a supernodal matrix with the storage type SLU SC. Due to the supernodal structure, L
is in fact stored as a sparse block lower triangular matrix [6].
typedef struct {
int nnz; /*
number of nonzeros in the matrix */
int nsuper; /*
index of the last supernode */
void *nzval; /*
array of nonzero values packed by column */
int *nzval_colptr; /*
nzval_colptr[j] stores the location in
nzval[] which starts column j */
int *rowind; /* array of compressed row indices of
rectangular supernodes */
int *rowind_colptr;/* rowind_colptr[j] stores the location in
rowind[] which starts column j */
int *col_to_sup; /* col_to_sup[j] is the supernode number to
21
which column j belongs */
int *sup_to_col; /* sup_to_col[s] points to the starting column
of the s-th supernode */
} SCformat;
• Both B and X are stored as conventional two-dimensional arrays in column-major order, with
the storage type SLU DN.
typedef struct {
int lda; /* leading dimension */
void *nzval; /* array of size lda-by-ncol to represent
a dense matrix */
} DNformat;
Figure 2.3 shows the data structures for the example matrices in Figure 2.1.
For a description of NCPformat, see section 2.5.1.
• Fact
Specifies whether or not the factored form of the matrix A is supplied on entry, and if not,
how the matrix A will be factorized base on the previous history, such as factor from scratch,
reuse Pc and/or Pr , or reuse the data structures of L and U . fact can be one of:
22
• A = { Stype = SLU_NC; Dtype = SLU_D; Mtype = SLU_GE; nrow = 5; ncol = 5;
*Store = { nnz = 12;
nzval = [ 19.00, 12.00, 12.00, 21.00, 12.00, 12.00, 21.00,
16.00, 21.00, 5.00, 21.00, 18.00 ];
rowind = [ 0, 1, 4, 1, 2, 4, 0, 2, 0, 3, 3, 4 ];
colptr = [ 0, 3, 6, 8, 10, 12 ];
}
}
Figure 2.3: The data structures for a 5 × 5 matrix and its LU factors, as represented in the
SuperMatrix data structure. Zero-based indexing is used.
23
• Equil { YES | NO }
Specifies whether to equilibrate the system (scale A’s rows and columns to have unit norm).
• ColPerm
Specifies how to permute the columns of the matrix for sparsity preservation.
• IterRefine
Specifies whether to perform iterative refinement, and in what precision to compute the
residual.
• SymmetricMode { YES | NO }
Specifies whether to use the symmetric mode. Symmetric mode gives preference to diagonal
pivots, and uses an (AT + A)-based column permutation algorithm.
• PivotGrowth { YES | NO }
Specifies whether to compute the reciprocal pivot growth.
• ConditionNumber { YES | NO }
Specifies whether to compute the reciprocal condition number.
24
• ILU DropRule
Specifies the dropping rule for ILU: ( Default: DROP BASIC | DROP AREA )
• PrintStat { YES | NO }
Specifies whether to print the solver’s statistics.
The routine set default options() sets the following default values:
To use the ILU routines, such as dgsitrf(), the user should call ilu set default options() to
set the default values (set default options() is first called in this routine prior to the following):
25
ILU_FillFactor = 10.0;
ILU_Norm = INF_NORM;
ILU_MILU = SILU; /* not to use MILU */
ILU_FillTol = 1e-2;
The other possible values for each field are documented in the source code SRC/slu util.h.
The users can reset each default value according to their needs.
2.5 Permutations
Two permutation matrices are involved in the solution process. In fact, the actual factorization we
perform is Pr APcT = LU , where Pr is determined from partial pivoting (with a threshold pivoting
option), and Pc is a column permutation chosen either by the user or SuperLU, usually to make the
L and U factors as sparse as possible. Pr and Pc are represented by two integer vectors perm r[]
and perm c[], which are the permutations of the integers (0 : m − 1) and (0 : n − 1), respectively.
• MY PERMC: use the ordering given in the permutation vector perm c[], which is input by the
user.
If [Link] is set to the last value, the library will use the permutation vector perm c[]
as an input, which may be obtained from any other ordering algorithm. For example, the nested-
dissection type of ordering codes include Metis [20], Chaco [18] and Scotch [31].
Alternatively, the users can provide their own column permutation vector. For example, it
may be an ordering suitable for the underlying physical problem. Both driver routines dgssv and
dgssvx take perm c[] as an input argument.
After permutation Pc is applied to A, we use SLU NCP format to represent the permuted matrix
APcT , in which the consecutive columns of nonzeros may not be stored contiguously in memory.
Therefore, we need two separate arrays of pointers, colbeg[] and colend[], to indicate the be-
ginning and end of each column in nzval[] and rowind[].
typedef struct {
int nnz; /* number of nonzeros in the matrix */
26
void *nzval; /* array of nonzero values, packed by column */
int *rowind; /* array of row indices of the nonzeros */
int *colbeg; /* colbeg[j] points to the location in nzval[] and rowind[]
which starts column j */
int *colend; /* colend[j] points to one past the location in nzval[]
and rowind[] which ends column j */
} NCPformat;
(2) if user specifies pivot row k and |akj | ≥ thresh and akj 6= 0 then
pivot row = k;
else if |ajj | ≥ thresh and ajj 6= 0 then
pivot row = j;
else
pivot row = m;
endif;
• u = 0.0: either use user-specified pivot order if available, or else use diagonal pivot;
27
2.7 Incomplete LU factorization (ILU) preconditioner
Starting from SuperLU version 4.0, we provide the ILU routines to be used as preconditioners
for iterative solvers. Our ILU method can be considered to be a variant of the ILUTP method
originally proposed by Saad [33], which combines a dual dropping strategy with numerical pivoting
(“T” stands for threshold, and “P” stands for pivoting). We adapted the classic dropping strategies
of ILUTP in order to incorporate supernode structures and to accommodate dynamic supernodes
due to partial pivoting. For the secondary dropping strategy, we proposed an area-based fill control
method, which is more flexible and numerically robust than the traditional column-based scheme.
Furthermore, we incorporated several heuristics for adaptively modifying various threshold param-
eters as the factorization proceeds, which improves the robustness of the algorithm. The details
can be found in [27].
• user-level – based on a user-supplied work[] array of size lwork (in bytes). This is similar
to Fortran-style handling of work space. Work[] is organized as a two-ended stack, one end
holding the L and U data structures, the other end holding the auxiliary arrays of known
size.
Except for the different ways to allocate/deallocate space, the logical view of the memory
organization is the same for both schemes. Now we describe the policies in the memory module.
At the outset of the factorization, we guess there will be FILL*nnz(A) fills in the factors and
allocate corresponding storage for the above four arrays, where nnz(A) is the number of nonzeros in
original matrix A, and FILL is an integer, say 20. (The value of FILL can be set in an inquiry function
sp ienv(), see section 2.11.3.) If this initial request exceeds the physical memory constraint, the
FILL factor is repeatedly reduced, and attempts are made to allocate smaller arrays, until the initial
allocation succeeds.
During the factorization, if any array size exceeds the allocated bound, we expand it as follows.
We first allocate a chunk of new memory of size EXPAND times the old size, then copy the existing
data into the new memory, and then free the old storage. The extra copying is necessary, because the
factorization algorithm requires that each of the aforementioned four data structures be contiguous
in memory. The values of FILL and EXPAND are normally set to 20 and 1.5, respectively. See
xmemory.c for details.
After factorization, we do not garbage-collect the extra space that may have been allocated.
Thus, there will be external fragmentation in the L and U data structures. The settings of FILL and
EXPAND should take into account the trade-off between the number of expansions and the amount
of fragmentation.
28
Arrays of known size, such as various column pointers and working arrays, are allocated just
once. All dynamically-allocated working arrays are freed after factorization.
• dgstrf(): Factorize.
This implements the first-time factorization, or later re-factorization with the same nonzero
pattern. In re-factorizations, the code has the ability to use the same column permutation Pc
and row permutation Pr obtained from a previous factorization. The input argument options
contains several scalar arguments to control how the LU decomposition and the numerical
pivoting should be performed. dgstrf() can handle non-square matrices.
29
• dgsitrf(): ILU.
This implements the incomplete LU factorization The input argument options contains sev-
eral scalar arguments to control how the incomplete facotirzation and the numerical pivoting
should be performed.
• dgsequ()/dlaqgs(): Equilibrate.
dgsequ first computes the row and column scalings Dr and Dc which would make each row
and each column of the scaled matrix Dr ADc have equal norm. dlaqgs then applies them to
the original matrix A if it is indeed badly scaled. The equilibrated A overwrites the original
A.
30
dCreate_Dense_Matrix(SuperMatrix *X, int m, int n, double *x, int ldx,
Stype_t stype, Dtype_t dtype, Mtype_t mtype);
31
Superlu and lusolve correspond to the two Matlab built-in functions lu and \ . In Matlab, when
you type
help superlu
you will find the following description about superlu’s functionality and how to use it.
Executive summary:
With one input and two or three outputs, SUPERLU has the same effect as LU,
except that the pivoting permutation is returned as a vector, not a matrix:
32
[L,U,prow,pcol] = superlu(A) is the same as ... = superlu(A,colmmd(A));
it uses column minimum degree to permute columns for sparsity,
then postorders the etree and factors.
For a description about lusolve’s functionality and how to use it, you can type
help lusolve
Two M-files trysuperlu.m and trylusolve.m are written to test the correctness of superlu
and lusolve. In addition to testing the residual norms, they also test the function invocations
with various number of input/output arguments.
2.11 Installation
2.11.1 File structure
The top level SuperLU/ directory is structured as follows:
Before installing the package, you may need to edit SuperLU/[Link] for your system. This
make include file is referenced inside each of the Makefiles in the various subdirectories. As a
33
result, there is no need to edit the Makefiles in the subdirectories. All information that is machine
specific has been defined in [Link].
Sample machine-specific [Link] are provided in the MAKE INC/ subdirectory for several sys-
tems, including IBM RS/6000, DEC Alpha, SunOS 4.x, SunOS 5.x (Solaris), HP-PA and SGI Iris
4.x. When you have selected the machine on which you wish to install SuperLU, you may copy the
appropriate sample include file (if one is present) into [Link]. For example, if you wish to run
SuperLU on an IBM RS/6000, you can do:
cp MAKE INC/make.rs6k [Link]
For systems other than those listed above, slight modifications to the [Link] file will need
to be made. In particular, the following three items should be examined:
34
Test Type Test ratio Routines
Matrix type Description
0 ||LU − A||/(n||A||ε) dgstrf
0 sparse matrix g10
1 ||b − Ax||/(||A|| ||x||ε) dgssv, dgssvx
1 diagonal
2 ||x − x∗ ||/(||x∗ ||κε) dgssvx
2 upper triangular
3 ||x − x∗ ||/(||x∗ || F ERR) dgssvx
3 lower triangular
4 BERR/ε dgssvx
4 random, κ = 2
5 first column zero
6 last column zero Table 2.2: Types of tests. x∗ is the true solution,
7 last n/2 columns
p zero F ERR is the error bound, and BERR is the
8 random, κ = 0.1/ε backward error.
9 random, κ = 0.1/ε
10 scaled near underflow
11 scaled near overflow
trysuperlu
trylusolve
A Makefile is provided in each subdirectory. The installation can be done completely auto-
matically by simply typing make at the top level.
2.11.2 Testing
The test programs in SuperLU/INSTALL subdirectory test two routines:
• slamch()/dlamch() determines properties of the floating-point arithmetic at run-time (both
single and double precision), such as the machine epsilon, underflow threshold, overflow
threshold, and related parameters;
• SuperLU timer () returns the time in seconds used by the process. This function may need
to be modified to run on your machine.
The test programs in the SuperLU/TESTING subdirectory are designed to test all the functions of
the driver routines, especially the expert drivers. The Unix shell script files [Link] are used to
invoke tests with varying parameter settings. The input matrices include an actual sparse matrix
SuperLU/EXAMPLE/g10 of dimension 100 × 100,3 and numerous matrices with special properties
from the LAPACK test suite. Table 2.1 describes the properties of the test matrices.
For each command line option specified in [Link], the test program ddrive reads in or
generates an appropriate matrix, calls the driver routines, and computes a number of test ratios
3
Matrix g10 is first generated with the structure of the 10-by-10 five-point grid, and random numerical values.
The columns are then permuted by COLMMD ordering from Matlab.
35
to verify that each operation has performed correctly. If the test ratio is smaller than a preset
threshold, the operation is considered to be correct. Each test matrix is subject to the tests listed
in Table 2.2.
Let r be the residual r = b − Ax, and let mi be the number of nonzeros in row i of A. Then
the componentwise backward error BERR and forward error F ERR [1] are calculated by:
|r|i
BERR = max .
i (|A| |x| + |b|)i
|| |A−1 | f ||∞
F ERR = .
||x||∞
Here, f is a nonnegative vector whose components are computed as fi = |r|i + mi ε (|A| |x| + |b|)i ,
and the norm in the numerator is estimated using the same subroutine used for estimating the
condition number. BERR measures the smallest relative perturbation one can make to each entry
of A and of b so that the computed solution is an exact solution of the perturbed problem. F ERR
is an estimated bound on the error kx∗ − xk∞ /kxk∞ , where x∗ is the true solution. For further
details on error analysis and error bounds estimation, see [1, Chapter 4] and [2].
Users are encouraged to modify this subroutine to set the tuning parameters for their own local
environment. The optimal values depend mainly on the cache size and the BLAS speed. If your
system has a very small cache, or if you want to efficiently utilize the closest cache in a multilevel
cache organization, you should pay special attention to these parameter settings. In our technical
paper [6], we described a detailed methodology for setting these parameters for high performance.
The relax parameter is usually set between 4 and 8. The other parameter values which give
good performance on several machines are listed in Table 2.3. In a supernode-panel update, if the
updating supernode is too large to fit in cache, then a 2D block partitioning of the supernode is
used, in which rowblk and colblk determine that a block of size rowblk × colblk is used to update
current panel.
If colblk is set greater than maxsup, then the program will never use 2D blocking. For example,
for the Cray J90 (which does not have cache), w = 1 and 1D blocking give good performance; more
levels of blocking only increase overhead.
36
On-chip External
Machine Cache Cache w maxsup rowblk colblk
RS/6000-590 256 KB – 8 100 200 40
MIPS R8000 16 KB 4 MB 20 100 800 100
Alpha 21064 8 KB 512 KB 8 100 400 40
Alpha 21164 8 KB-L1 4 MB 16 50 100 40
96 KB-L2
Sparc 20 16 KB 1 MB 8 100 400 50
UltraSparc-I 16 KB 512 KB 8 100 400 40
Cray J90 – – 1 100 1000 100
• dlinsol: use simple driver dgssv() to solve a linear system one time.
• dlinsolx: use dgssvx() with the full (default) set of options to solve a linear system.
• dlinsolx1: use dgssvx() to factorize A first, then solve the system later.
• dlinsolx2: use dgssvx() to solve systems repeatedly with the same sparsity pattern of
matrix A.
In this directory, a Makefile is provided to generate the executables, and a README file describes
how to run these examples.
• Arguments in C are passed by value, while in Fortran are passed by reference. So we always
pass the address (as a pointer) in the C calling routine. (You cannot make a call with numbers
directly in the parameters.)
• Fortran uses 1-based array addressing, while C uses 0-based. Therefore, the row indices
(rowind[]) and the integer pointers to arrays (colptr[]) should be adjusted before they are
passed into a C routine.
37
Because of the above language differences, in order to embed SuperLU in a Fortran environment,
users are required to use “wrapper” routines (in C) for all the SuperLU routines that will be called
from Fortran programs. The example c fortran dgssv.c in the FORTRAN/ directory shows how a
wrapper program should be written. This program is listed below.
#include "dsp_defs.h"
#define HANDLE_SIZE 8
typedef struct {
SuperMatrix *L;
SuperMatrix *U;
int *perm_c;
int *perm_r;
} factors_t;
int
c_fortran_dgssv_(int *iopt, int *n, int *nnz, int *nrhs, double *values,
int *rowind, int *colptr, double *b, int *ldb,
int factors[HANDLE_SIZE], /* a handle containing the pointer
to the factored matrices */
int *info)
{
/*
* This routine can be called from Fortran.
*
* iopt (input) int
* Specifies the operation:
* = 1, performs LU decomposition for the first time
* = 2, performs triangular solve
* = 3, free all the storage in the end
*
* factors (input/output) integer array of size 8
* If iopt == 1, it is an output and contains the pointer pointing to
* the structure of the factored matrices.
* Otherwise, it it an input.
*
*/
SuperMatrix A, AC, B;
SuperMatrix *L, *U;
int *perm_r; /* row permutations from partial pivoting */
int *perm_c; /* column permutation vector */
int *etree; /* column elimination tree */
SCformat *Lstore;
NCformat *Ustore;
38
int i, panel_size, permc_spec, relax;
trans_t trans;
double drop_tol = 0.0;
mem_usage_t mem_usage;
superlu_options_t options;
SuperLUStat_t stat;
factors_t *LUfactors;
trans = NOTRANS;
if ( *iopt == 1 ) { /* LU decomposition */
/*
* Get column permutation vector perm_c[], according to permc_spec:
* permc_spec = 0: natural ordering
* permc_spec = 1: minimum degree on structure of A’*A
* permc_spec = 2: minimum degree on structure of A’+A
* permc_spec = 3: approximate minimum degree for unsymmetric matrices
*/
permc_spec = 3;
get_perm_c(permc_spec, &A, perm_c);
panel_size = sp_ienv(1);
relax = sp_ienv(2);
39
dgstrf(&options, &AC, drop_tol, relax, panel_size,
etree, NULL, 0, perm_c, perm_r, L, U, &stat, info);
if ( *info == 0 ) {
Lstore = (SCformat *) L->Store;
Ustore = (NCformat *) U->Store;
printf("No of nonzeros in factor L = %d\n", Lstore->nnz);
printf("No of nonzeros in factor U = %d\n", Ustore->nnz);
printf("No of nonzeros in L+U = %d\n", Lstore->nnz + Ustore->nnz);
dQuerySpace(L, U, &mem_usage);
printf("L\\U MB %.3f\ttotal MB needed %.3f\texpansions %d\n",
mem_usage.for_lu/1e6, mem_usage.total_needed/1e6,
mem_usage.expansions);
} else {
printf("dgstrf() error returns INFO= %d\n", *info);
if ( *info <= *n ) { /* factorization completes */
dQuerySpace(L, U, &mem_usage);
printf("L\\U MB %.3f\ttotal MB needed %.3f\texpansions %d\n",
mem_usage.for_lu/1e6, mem_usage.total_needed/1e6,
mem_usage.expansions);
}
}
40
/* Extract the LU factors in the factors handle */
LUfactors = (factors_t*) factors[0];
L = LUfactors->L;
U = LUfactors->U;
perm_c = LUfactors->perm_c;
perm_r = LUfactors->perm_r;
Destroy_SuperMatrix_Store(&B);
StatFree(&stat);
Since the matrix structures in C cannot be directly returned to Fortran, we use a handle named
factors to access those structures. The handle is essentially an integer pointer pointing to the
factored matrices obtained from SuperLU. So the factored matrices are opaque objects to the Fortran
program, but can only be manipulated from the C wrapper program.
The Fortran program FORTRAN/f77 main.f shows how a Fortran program may call
c fortran dgssv(), and is listed below. A README file in this directory describes how to compile
and run this program.
program f77_main
integer maxn, maxnz
parameter ( maxn = 10000, maxnz = 100000 )
integer rowind(maxnz), colptr(maxn)
real*8 values(maxnz), b(maxn)
integer n, nnz, nrhs, ldb, info
integer factors(8), iopt
41
*
* Read the matrix file in Harwell-Boeing format
call hbcode1(n, n, nnz, values, rowind, colptr)
*
nrhs = 1
ldb = n
do i = 1, n
b(i) = 1
enddo
*
* First, factorize the matrix. The factors are stored in factor() handle.
iopt = 1
call c_fortran_dgssv( iopt, n, nnz, nrhs, values, rowind, colptr,
$ b, ldb, factors, info )
*
if (info .eq. 0) then
write (*,*) ’Factorization succeeded’
else
write(*,*) ’INFO from factorization = ’, info
endif
*
* Second, solve the system using the existing factors.
iopt = 2
call c_fortran_dgssv( iopt, n, nnz, nrhs, values, rowind, colptr,
$ b, ldb, factors, info )
*
if (info .eq. 0) then
write (*,*) ’Solve succeeded’
write (*,*) (b(i), i=1, 10)
else
write(*,*) ’INFO from triangular solve = ’, info
endif
42
Chapter 3
Table 3.1: The differences between the parallel and the sequential algorithms.
43
typedef struct {
int nnz; /* number of nonzeros in the matrix */
int nsuper; /* number of supernodes */
void *nzval; /* pointer to array of nonzero values,
packed by column */
int *nzval_colbeg; /* nzval_colbeg[j] points to beginning of column j
in nzval[] */
int *nzval_colend; /* nzval_colend[j] points to one past the last
element of column j in nzval[] */
int *rowind; /* pointer to array of compressed row indices of
the supernodes */
int *rowind_colbeg;/* rowind_colbeg[j] points to beginning of column j
in rowind[] */
int *rowind_colend;/* rowind_colend[j] points to one past the last
element of column j in rowind[] */
int *col_to_sup; /* col_to_sup[j] is the supernode number to which
column j belongs */
int *sup_to_colbeg;/* sup_to_colbeg[s] points to the first column
of the s-th supernode /
int *sup_to_colend;/* sup_to_colend[s] points to one past the last
column of the s-th supernode */
} SCPformat;
A L U B X
Stype SLU NC or SLU NR SLU SCP SLU NCP SLU DN SLU DN
Dtype any any any any any
Mtype SLU GE SLU TRLU SLU TRU SLU GE SLU GE
44
• nprocs
Specifies the number of threads to be spawned.
• Fact
Specifies whether or not the factored form of the matrix A is supplied on entry, and if not,
how the matrix A will be factorized base on the previous history, such as factor from scratch,
reuse Pc and/or Pr , or reuse the data structures of L and U . fact can be one of:
• panel size
Specifies the number of consecutive columns to be treated as a unit of task.
• relax
Specifies the number of columns to be grouped as a relaxed supernode.
• refact { YES | NO }
Specifies whether this is first time or subsequent factorization.
• SymmetricMode { YES | NO }
Specifies whether to use the symmetric mode.
• PrintStat { YES | NO }
Specifies whether to print the solver’s statistics.
• A simple driver pdgssv, which solves the system AX = B by factorizing A and overwriting
B with the solution X.
45
• An expert driver pdgssvx, which, in addition to the above, also performs the following func-
tions (some of them optionally):
– solve AT X = B;
– equilibrate the system (scale A’s rows and columns to have unit norm) if A is poorly
scaled;
– estimate the condition number of A, check for near-singularity, and check for pivot
growth;
– refine the solution and compute forward and backward error bounds.
• dgsequ/dlaqgs: Equilibrate.
dgsequ first computes the row and column scalings Dr and Dc which would make each row
and each column of the scaled matrix Dr ADc have equal norm. dlaqgs then applies them to
the original matrix A if it is indeed badly scaled. The equilibrated A overwrites the original
A.
46
3.5 Installation
3.5.1 File structure
The top level SuperLU MT/ directory is structured as follows:
We have ported the parallel programs to a number of platforms, which are reflected in the
make include files provided in the top level directory, for example, [Link], [Link],
[Link], [Link], [Link], [Link]. If you are using one of these machines, such as an
IBM, you can simply copy [Link] into [Link] before compiling. If you are not using any of the
machines to which we have ported, you will need to read section 3.7 about the porting instructions.
The rest of the installation and testing procedure is similar to that described in section 2.11 for
the serial SuperLU. Then, you can type make at the top level directory to finish installation. In
the SuperLU MT/TESTING subdirectory, you can type [Link] to perform testings.
47
exceeds the physical memory constraint, the sizes of the arrays are repeatedly reduced until the
initial allocation succeeds.
int sp ienv(int ispec);
Ispec specifies the parameter to be returned:
ispec = ...
= 6: size of the array to store the values of the L supernodes (nzval)
= 7: size of the array to store the columns in U (nzval/rowind)
= 8: size of the array to store the subscripts of the L supernodes (rowind);
If the actual fill exceeds any array size, the program will abort with a message showing the
current column when failure occurs, and indicating how many elements are needed up to the
current column. The user may reset a larger fill parameter for this array and then restart the
program.
To make the storage allocation more efficient for the supernodes in L, we devised a special
storage scheme. The need for this special treatment and how we implement it are fully explained
and studied in [7, 23]. Here, we only sketch the main idea. Recall that the parallel algorithm assigns
one panel of columns to one process. Two consecutive panels may be assigned to two different
processes, even though they may belong to the same supernode discovered later. Moreover, a third
panel may be finished by a third process and put in memory between these two panels, resulting
in the columns of a supernode being noncontiguous in memory. This is undesirable, because then
we cannot directly call BLAS routines using this supernode unless we pay the cost of copying the
columns into contiguous memory first. To overcome this problem, we exploited the observation that
the nonzero structure for L is contained in that of the Householder matrix H from the Householder
sparse QR transformation [13, 14]. Furthermore, it can be shown that a fundamental supernode of
L is always contained in a fundamental supernode of H. This containment property is true for any
row permutation Pr in Pr A = LU . Therefore, we can pre-allocate storage for the L supernodes
based on the size of H supernodes. Fortunately, there exists a fast algorithm (almost linear in the
number of nonzeros of A) to compute the size of H and the supernodes partition in H [15].
In practice, the above static prediction is fairly tight for most problems. However, for some
others, the number of nonzeros in H greatly exceeds the number of nonzeros in L. To handle
this situation, we implemented an algorithm that still uses the supernodes partition in H, but
dynamically searches the supernodal graph of L to obtain a much tighter bound for the storage.
Table 6 in [7] demonstrates the storage efficiency achieved by both static and dynamic approach.
In summary, our program tries to use the static prediction first for the L supernodes. In this
case, we ignore the integer value given in the function sp ienv(6), and simply use the nonzero
count of H. If the user finds that the size of H is too large, he can invoke the dynamic algorithm
at runtime by setting the following Linux shell environment variable:
setenv SuperLU DYNAMIC SNODE STORE 1
The dynamic algorithm incurs runtime overhead. For example, this overhead is usually between
2% and 15% on a single processor RS/6000-590 for a range of test matrices.
48
Symmetric structure pruning
In both serial and parallel algorithms, we have implemented Eisenstat and Liu’s symmetric pruning
idea of representing the graph G(LT ) by a reduced graph G0 , and thereby reducing the DFS traversal
time. A subtle difficulty arises in the parallel implementation.
When the owning process of a panel starts DFS (depth-first search) on G0 built so far, it
only sees the partial graph, because the part of G0 corresponding to the busy panels down the
elimination tree is not yet complete. So the structural prediction at this stage can miss some
nonzeros. After performing the updates from the finished supernodes, the process will wait for
all the busy descendant panels to finish and perform more updates from them. Now, we make
a conservative assumption that all these busy panels will update the current panel so that their
nonzero structures are included in the current panel.
This approximate scheme works fine for most problems. However, we found that this conser-
vatism may sometimes cause a large number of structural zeros (they are related to the supernode
amalgamation performed at the bottom of the elimination tree) to be included and they in turn
are propagated through the rest of the factorization.
We have implemented an exact structural prediction scheme to overcome this problem. In this
scheme, when each numerical nonzero is scattered into the sparse accumulator array, we set the
occupied flag as well. Later when we accumulate the updates from the busy descendant panels, we
check the occupied flags to determine the exact nonzero structure. This scheme avoids unnecessary
zero propagation at the expense of runtime overhead, because setting the occupied flags must be
done in the inner loop of the numeric updates.
We recommend that the user use the approximate scheme (by default) first. If the user finds
that the amount of fill from the parallel factorization is substantially greater than that from the
sequential factorization, he can then use the accurate scheme. To invoke the second scheme, the
user should recompile the code by defining the macro:
-D SCATTER FOUND
for the C preprocessor.
49
Programming Environment
[Link] Platforms Model Variable
[Link] Machines with POSIX threads pthreads
[Link] Machines with OpenMP OpenMP OMP NUM THREADS
[Link] DEC Alpha Servers DECthreads
[Link] Cray C90/J90 microtasking NCPUS
[Link] IBM Power series pthreads
[Link] SGI/Cray Origin2000 parallel C MP SET NUMTHREADS
[Link] SGI Power Challenge parallel C MPC NUM THREADS
[Link] Sun Ultra Enterprise Solaris threads
We should take into account the trade-off between cache reuse and amount of parallelism in order
to set the appropriate w and maxsup. Since the parallel algorithm assigns one panel factorization to
one process, large values may constrain concurrency, even though they may be good for uniprocessor
performance. We recommend that w and maxsup be set a bit smaller than the best values used in
the sequential code.
The settings for parameters 2, 4 and 5 are the same as those described in section 2.11.3. The
settings for parameters 6, 7 and 8 are discussed in section 3.5.2.
In the file SRC/sp ienv.c, we provide sample settings of these parameters for several machines.
50
Mutex Critical region
ULOCK allocate storage for a column of matrix U
LLOCK allocate storage for row subscripts of matrix L
LULOCK allocate storage for the values of the supernodes
NSUPER LOCK increment supernode number nsuper
SCHED LOCK invoke Scheduler() which may update global task queue
In the source code, all the platform specific constructs are enclosed in the C #ifdef preprocessor
statement. If your platform is different from any one listed in Table 3.2, you need to go to these
places and create the parallel constructs suitable for your machine. The two constructs, concurrency
and synchronization, are explained in the following two subsections, respectively.
51
Chapter 4
Distributed-memory SuperLU on
manycore nodes (Version 4.0)
52
typedef struct {
int nnz_loc; /* number of nonzeros in the local submatrix */
int m_loc; /* number of rows local to this process */
int fst_row; /* row number of the first row in the local submatrix */
void *nzval; /* pointer to array of nonzero values, packed by row */
int *rowptr; /* pointer to array of beginning of rows in nzval[]
and colind[] */
int *colind; /* pointer to array of column indices of the nonzeros */
} NRformat_loc;
Let mi be the number of rows owned by the ith process. Then the global row dimension for A
PP −1
is nrow = i=0 mi . The global column dimension is ncol. Both nrow and ncol are recorded in
the higher level SuperMatrix data structure, see Figure 2.2. The utility routine
dCreate CompRowLoc Matrix dist can help the user to create the structure for A. The definition
of this routine is
where, the first argument is output and the rest are inputs.
The local full matrix B is stored in the standard Fortran-style column major format, with
dimension m loc × nrhs, and ldb refers to the local leading dimension in the local storage.
53
Figure 4.1: The 2 block-cyclic layout and the data structure to store a local block column of L.
hence not stored. Neither do we store the zeros in a nonzero block. Both lower and upper triangles
of the diagonal block are stored in the L data structure. A process owns dN/npcole block columns
of L, so it needs dN/nprowe pairs of index/nzval arrays.
For U , we use a row oriented storage for the block rows owned by a process, although for the
numerical values within each block we still use column major order. Similar to L, we also use a pair
of index/nzval arrays to store a block row of U . Due to asymmetry, each nonzero block in U has
the skyline structure as shown in Figure 4.1 (see [6] for details on the skyline structure). Therefore,
the organization of the index[] array is different from that for L, which we omit showing in the
figure.
54
superlu_gridinit(MPI_Comm Bcomm, int nprow, int npcol, gridinfo_t *grid);
This process grid will use the first nprow ∗ npcol processes from the base MPI communicator
Bcomm, and assign them to the grid in a row-major ordering. The input argument Bcomm is an MPI
communicator representing the existing base group upon which the new group will be formed. For
example, it can be MPI COMM WORLD. The output argument grid represents the derived group to be
used in SuperLU DIST. Grid is a structure containing the following fields:
struct {
MPI_Comm comm; /* MPI communicator for this group */
int iam; /* my process rank in this group */
int nprow; /* number of process rows */
int npcol; /* number of process columns */
superlu_scope_t rscp; /* process row scope */
superlu_scope_t cscp; /* process column scope */
} grid;
In the LU factorization, some communications occur only among the processes in a row (col-
umn), not among all processes. For this purpose, we introduce two process subgroups, namely rscp
(row scope) and cscp (column scope). For rscp (cscp) subgroup, all processes in a row (column)
participate in the communication.
The macros MYROW(iam, grid) and MYCOL(iam, grid) give the row and column coordinates
in the 2D grid of the process who has rank iam.
NOTE: All processes in the base group, including those not in the new group, must call this grid
creation routine. This is required by the MPI routine MPI Comm create to create a new communi-
cator.
55
NOTE: All processes in the base group, including those not in the new group, must call this
routine.
Superlu gridinit simply calls superlu gridmap with usermap[] holding the first nprow ∗
npcol process ranks.
Step (1) is accomplished by a weighted bipartite matching algorithm due to Duff and Koster [10].
Currently, process 0 computes Pr and then broadcasts it to all the other processes. If the distributed
input interface is used (Section 4.2.2), we first gather the distributed matrix A onto processor 0.
Work is underway to remove this sequential bottleneck.
In Step (2), we provide several ordering options, such as multiple minimum degree ordering [28]
on the graphs of A + AT , or the MeTiS [20] ordering on the graphs of A + AT . The user can use
56
any other ordering in place of the ones provided in the library. (Note, since we will pivot on the
diagonal in step (4), an ordering based on the structure of A + AT almost always yields sparser
factors than that based on the structure of AT A. This is different from SuperLU and SuperLU MT,
where we allow to pivot off-diagonal.) In this step, when a sequential ordering algorithm is used,
every process runs the same algorithm independently.
Step (3) can be done either sequentially or in parallel depending on how the options argument
is set (see Section 4.8.1 for details.) The parallel symbolic factorization was a newly added feature
since the v2.1 release. It is designed tightly around the separator tree returned from a graph
partitioning type of ordering (presently we use ParMeTiS [21]), and works only on power-of-two
processors. We first re-distribute the graph of A onto the largest 2q number of processors which
is smaller than the total Np processors, then perform parallel symbolic factorization, and finally
re-populate the {L\U } structure to all Np processors. The algorithm and performance was studied
in [17]. To invoke parallel symbolic factorization, the user needs to set the two fields of the options
argument as follows:
[Link] = YES
[Link] = PARMETIS;
Note that, even if the user sets [Link] to use an ordering algorithm other than ParMeTiS,
the driver routine overrides it with ParMeTiS when it sees [Link] = YES.
Steps (4) to (7) are the most time-consuming steps and were parallelized a while ago, see the
papers [26, 24].
57
just setting OMP NUM THREADS would set the number of threads for both MKL and OpenMP. How-
ever, it is possible to have different number of threads for MKL, in which case MKL NUM THREADS
controls the number of threads used by MKL. In our case, just setting OMP NUM THREADS is sufficient.
Triangular solve phase does not use multithreading yet. The MPI-only configuration may be
more suitable in case of many right hand sides or in other cases, where solve phase seems to be a
performance bottleneck.
• Fact
Specifies whether or not the factored form of the matrix A is supplied on entry, and if not,
how the matrix A will be factored base on some assumptions of the previous history. fact
can be one of:
• Equil { YES | NO }
Specifies whether to equilibrate the system.
• ParSymbFact { YES | NO }
Specifies whether to perform parallel symbolic factorization. If it is set to YES, the ColPerm
field should be set to PARMETIS. Otherwise, the driver routine pdgssvx will use ParMeTiS
anyway, ignoring the other setting in ColPerm.
• ColPerm
Specifies the column ordering method for fill reduction.
58
– NATURAL: natural ordering.
– MMD AT PLUS A: minimum degree ordering on the structure of AT + A.
– MMD ATA: minimum degree ordering on the structure of AT A.
– METIS AT PLUS A: MeTiS ordering on the structure of AT + A.
– PARMETIS: ParMeTiS ordering on the structure of AT + A.
– MY PERMC: use the ordering given in perm c input by the user.
• RowPerm
Specifies how to permute rows of the original matrix.
• ReplaceTinyPivot { YES | NO }
√
Specifies whether to replace the tiny diagonals by ε · ||A|| during LU factorization.
• IterRefine
Specifies how to perform iterative refinement.
• SolveInitialized { YES | NO }
Specifies whether the initialization has been performed to the triangular solve.
(used only by the distributed input interface)
• RefineInitialized { YES | NO }
Specifies whether the initialization has been performed to the sparse matrix-vector multipli-
cation routine needed in the iterative refinement.
(used only by the distributed input interface)
59
• SymPattern { YES | NO }
Gives the scheduling algorithm a hint whether the matrix has the symmetric pattern.
• PrintStat { YES | NO }
Specifies whether to print the solver’s statistics.
There is a routine named set default options dist() that sets the default values of these
options, which are:
fact = DOFACT /* factor from scratch */
equil = YES
ParSymbFact = NO
colperm = MMD_AT_PLUS_A
rowperm = LargeDiag /* use MC64 */
ReplaceTinyPivot = YES
IterRefine = DOUBLE
Trans = NOTRANS
SolveInitialized = NO
RefineInitialized = NO
num_lookaheads = 10;
lookahead_etree = NO;
SymPattern = NO;
PrintStat = YES
#include <math.h>
#include "superlu_ddefs.h"
60
* 2. Set up the input matrix and the right-hand side
* 3. Set the options argument
* 4. Call pdgssvx
* 5. Release the process grid and terminate the MPI environment
*
* On the Cray T3E, the program may be run by typing
* mpprun -n <procs> pddrive -r <proc rows> -c <proc columns> <input_file>
*
*/
{
superlu_options_t options;
SuperLUStat_t stat;
SuperMatrix A;
ScalePermstruct_t ScalePermstruct;
LUstruct_t LUstruct;
SOLVEstruct_t SOLVEstruct;
gridinfo_t grid;
double *berr;
double *b, *xtrue;
int_t m, n, nnz;
int_t nprow, npcol;
int iam, info, ldb, ldx, nrhs;
char trans[1];
char **cpp, c;
FILE *fp, *fopen();
/* ------------------------------------------------------------
INITIALIZE MPI ENVIRONMENT.
------------------------------------------------------------*/
MPI_Init( &argc, &argv );
61
exit(0);
break;
case ’r’: nprow = atoi(*cpp);
break;
case ’c’: npcol = atoi(*cpp);
break;
}
} else { /* Last arg is considered a filename */
if ( !(fp = fopen(*cpp, "r")) ) {
ABORT("File does not exist");
}
break;
}
}
/* ------------------------------------------------------------
INITIALIZE THE SUPERLU PROCESS GRID.
------------------------------------------------------------*/
superlu_gridinit(MPI_COMM_WORLD, nprow, npcol, &grid);
/* ------------------------------------------------------------
GET THE MATRIX FROM FILE AND SETUP THE RIGHT HAND SIDE.
------------------------------------------------------------*/
dcreate_matrix(&A, nrhs, &b, &ldb, &xtrue, &ldx, fp, &grid);
if ( !(berr = doubleMalloc_dist(nrhs)) )
ABORT("Malloc fails for berr[].");
/* ------------------------------------------------------------
NOW WE SOLVE THE LINEAR SYSTEM.
------------------------------------------------------------*/
m = [Link];
n = [Link];
62
/* Initialize the statistics variables. */
PStatInit(&stat);
/* ------------------------------------------------------------
DEALLOCATE STORAGE.
------------------------------------------------------------*/
PStatFree(&stat);
Destroy_CompRowLoc_Matrix_dist(&A);
ScalePermstructFree(&ScalePermstruct);
Destroy_LU(n, &grid, &LUstruct);
LUstructFree(&LUstruct);
if ( [Link] ) {
dSolveFinalize(&options, &SOLVEstruct);
}
SUPERLU_FREE(b);
SUPERLU_FREE(xtrue);
SUPERLU_FREE(berr);
/* ------------------------------------------------------------
RELEASE THE SUPERLU PROCESS GRID.
------------------------------------------------------------*/
out:
superlu_gridexit(&grid);
/* ------------------------------------------------------------
TERMINATES THE MPI EXECUTION ENVIRONMENT.
------------------------------------------------------------*/
MPI_Finalize();
}
Five basic steps are required to call a SuperLU routine:
1. Initialize the MPI environment and the SuperLU process grid.
63
This is achieved by the calls to the MPI routine MPI Init() and the SuperLU routine
superlu gridinit(). In this example, the communication domain for SuperLU is built upon
the MPI default communicator MPI COMM WORLD. In general, it can be built upon any MPI
communicator. Section 4.4 contains the details about this step.
• Equilibrate the system (scale A’s rows and columns to have unit norm) if A is poorly scaled;
• Find a row permutation that makes diagonal of A large relative to the off-diagonal;
• Find a column permutation that preserves the sparsity of the L and U factors;
64
• Solve the system AX = B for X by factoring A followed by forward and back substitutions;
65
/* Deallocate ScalePermstruct */
ScalePermstructFree(ScalePermstruct_t *ScalePermstruct);
/* Deallocate LUstruct. */
LUstructFree(LUstruct_t *LUstruct);
4.9 Installation
4.9.1 File structure and complilation
The top level SuperLU DIST/ directory is structured as follows:
You can use CMake automic build system to install the package. Please see [Link] for
instruction. The following describes how to install manually by editing a Makefile.
Before installing the package, you may need to edit SuperLU DIST/[Link] for your system.
This make include file is referenced inside all the Makefiles in the various subdirectories. As a
66
result, there is no need to edit the Makefiles in the subdirectories. All information that is machine
specific has been defined in this include file.
Sample machine-specific [Link] are provided in the MAKE INC/ directory for several platforms,
such as Cray XE6 and IBM SP. When you have selected the machine to which you wish to install
SuperLU DIST, you may copy the appropriate sample include file (if one is present) into [Link].
For example, if you wish to run on a Cray XE6, you can do:
cp MAKE INC/make.xe6 [Link]
For the systems other than those listed above, slight modifications to the [Link] file will
need to be made. In particular, the following items should be examined:
67
4. (optional) Enable Nvidia GPU access.
(a) Set the following Linux environment variable: setenv ACC GPU
(b) Add the CUDA library location in [Link]:
ifeq "${ACC}" "GPU"
CFLAGS += -DGPU_ACC
INCS += -I<CUDA directory>/include
LIBS += -L<CUDA directory>/lib64 -lcublas -lcudart
endif
-D_OPENMP
The values to be returned may be set differently on different machines. The setting of maximum
block size (parameter 3) should take into account the local Level 3 BLAS speed, the load balance and
the degree of parallelism. Small block size may result in better load balance and more parallelism,
but poor individual node performance, and vice versa for large block size.
These parameters can also be set as Linux environment variables, so that the routine sp ienv()
does not need to be recompiled every time when you change the settings.
setenv NREL <##> /* parameter #2: maximum size of the relaxed supernode */
setenv NSUP <##> /* parameter #3: maximum supernode size */
2
The numbering of 2, 3 and 6 is consistent with that used in SuperLU and SuperLU MT.
68
The following parameters are related to GPU usage:
These parameters are described in detail in various algorithm papers, see [24, 34].
superlu mod.f90 Fortran 90 module that defines the interface functions to access SuperLU DIST’s
data structures.
superlu c2f wrap.c C wrapper functions, callable from Fortran. The functions fall
into three classes: 1) Those that allocate a structure and return
a handle, or deallocate the memory of a structure. 2) Those that
get or set the value of a component of a struct. 3) Those that
are wrappers for SuperLU DIST functions.
Table 4.1: The Fortran 90 interface files and an example driver routine.
Note that in this interface, all objects (such as grid, options, etc.) in SuperLU DIST are opaque,
meaning their size and structure are not visible to the Fortran user. These opaque objects are
allocated, deallocated and operated in the C side and not directly accessible from Fortran side.
They can only be accessed via handles that exist in Fortran’s user space. In Fortran, all handles
69
have type INTEGER. Specifically, in our interface, the size of Fortran handle is defined by superlu ptr
in superlupara.f90. For different systems, the size might need to be changed. Then using these
handles, Fortran user can call C wrapper routines to manipulate the opaque objects. For example,
you can call f create gridinfo(grid handle) to allocate memory for structure grid, and return a handle
grid handle.
The sample program illustrates the basic steps required to use SuperLU DIST in Fortran to solve
systems of equations. These include how to set up the processor grid and the input matrix, how to
call the linear equation solver. This program is listed below, and is also available as f pddrive.f90 in
the subdirectory. Note that the routine must include the moudle superlu mod which contains the
definitions of all parameters and the Fortran wrapper functions. A Makefile is provided to generate
the executable. A README file in this directory shows how to run the example.
program f_pddrive
!
! Purpose
! =======
!
! The driver program F_PDDRIVE.
!
! This example illustrates how to use F_PDGSSVX with the full
! (default) options to solve a linear system.
!
! Seven basic steps are required:
! 1. Create C structures used in SuperLU
! 2. Initialize the MPI environment and the SuperLU process grid
! 3. Set up the input matrix and the right-hand side
! 4. Set the options argument
! 5. Call f_pdgssvx
! 6. Release the process grid and terminate the MPI environment
! 7. Release all structures
!
use superlu_mod
include ’mpif.h’
implicit none
integer maxn, maxnz, maxnrhs
parameter ( maxn = 10000, maxnz = 100000, maxnrhs = 10 )
integer rowind(maxnz), colptr(maxn)
real*8 values(maxnz), b(maxn), berr(maxnrhs)
integer n, m, nnz, nrhs, ldb, i, ierr, info, iam
integer nprow, npcol
integer init
integer(superlu_ptr) :: grid
integer(superlu_ptr) :: options
integer(superlu_ptr) :: ScalePermstruct
integer(superlu_ptr) :: LUstruct
70
integer(superlu_ptr) :: SOLVEstruct
integer(superlu_ptr) :: A
integer(superlu_ptr) :: stat
71
! Distribute the matrix to the gird
call f_dcreate_matrix_dist(A, m, n, nnz, values, rowind, colptr, grid)
if (info == 0) then
write (*,*) ’Backward error: ’, (berr(i), i = 1, nrhs)
else
write(*,*) ’INFO from f_pdgssvx = ’, info
endif
72
! Release the SuperLU process grid
100 call f_superlu_gridexit(grid)
stop
end
Similar to the driver routine pddrive.c in C, seven basic steps are required to call a SuperLU DIST
routine in Fortran:
2. Initialize the MPI environment and the SuperLU process grid. This is achieved by the calls to
mpi init() and the C wrapper routine f superlu gridinit(). Note that f superlu gridinit() requires
the numbers of row and column of the process grid. In this example, we set them to be 2,
respectively.
3. Set up the input matrix and the right-hand side. This example uses the distributed input
interface, so we need to convert the input matrix to the distributed compressed row format.
Process 0 first reads the input matrix stored on disk in Harwell-Boeing format by calling
Fortran routine hbcode1(). The file name in this example is [Link]. Then all processes
call a C wrapper routine f dcreate dist matrix() to distribute the matrix to all the processes
distributed by block rows. The right-hand side matrix in this example is a column vector of
all ones. Note that, before setting the right-hand side, we use get CompRowLoc Matrix() to
get the number of local rows in the distributed matrix A.
One important note is that all the C routines use 0-based indexing scheme. Therefore, after
process 0 reads the matrix in compressed column format, we decrement its column pointers
(colptr) and row indices (rowind) by 1 so they become 0-based indexing.
4. Set the input arguments: options, ScalePermstruct, LUstruct, and stat. The input argument
options controls how the linear system would be sloved. The routine f set default options dist()
sets the options argument so that the slover performs all the functionalities. You can also set it
according to your own needs, using a call to the Fortran routine set superlu options(). LUstruct
73
is the data struture in which the distributed L and U factors are stored. ScalePermstruct is
the data struture in which several vectors describing the transformations done to matrix A
are stored. stat is a structure collecting the statistcs about runtime and flop count. These
three structures can be set by calling the C wrapper “init” routines f XXXInit.
6. Release the process grid and terminate the MPI environment. After the computation on a pro-
cess grid has been completed, the process grid should be released by a call to f spuerlu gridexit().
When all computations have been completed, the C wrapper routine mpi finalize() should be
called.
7. Deallocate all the structures. First we need to deallocate the storage allocated by SuperLU DIST
by a set of “free” calls. Note that this should be called before f spuerlu gridexit(), since some of
the “free” calls use the grid. Then we call the C wrapper “destroy” routines f destroy XXX()
to destroy all the Fortran handles. Note that f destroy gridinfo() should be called after
f spuerlu gridexit().
74
integer, optional :: nrow, ncol, nnz_loc, nrow_loc, fst_row
75
void f_get_SuperMatrix(fptr *A, int *nrow, int *ncol)
void f_set_SuperMatrix(fptr *A, int *nrow, int *ncol)
void f_get_CompRowLoc_Matrix(fptr *A, int *m, int *n, int *nnz_loc,
int *m_loc, int *fst_row)
void f_set_CompRowLoc_Matrix(fptr *A, int *m, int *n, int *nnz_loc,
int *m_loc, int *fst_row)
void f_get_superlu_options(fptr *opt, int *Fact, int *Trans, int *Equil,
int *RowPerm, int *ColPerm, int *ReplaceTinyPivot,
int *IterRefine, int *SolveInitialized,
int *RefineInitialized)
void f_set_superlu_options(fptr *opt, int *Fact, int *Trans, int *Equil,
int *RowPerm, int *ColPerm, int *ReplaceTinyPivot,
int *IterRefine, int *SolveInitialized,
int *RefineInitialized)
76
Bibliography
[2] M. Arioli, J. W. Demmel, and I. S. Duff. Solving sparse linear systems with sparse backward
error. SIAM J. Matrix Anal. Appl., 10(2):165–190, April 1989.
[3] A. Azad, A. Buluc, X.S. Li, X. Wang, and J. Langguth. A Distributed-Memory Approximation
Algorithm for Maximum Weight Perfect Bipartite Matching. SIAM J. Scientific Computing,
2018. arXiv:1801.09809v1, 30 Jan 2018. Submitted.
[5] T. A. Davis, J. R. Gilbert, S. Larimore, and E. Ng. A column approximate minimum degree
ordering algorithm. ACM Trans. Mathematical Software, 30(3):353–376, 2004.
[7] J. W. Demmel, J. R. Gilbert, and X. S. Li. An asynchronous parallel supernodal algorithm for
sparse gaussian elimination. SIAM J. Matrix Analysis and Applications, 20(4):915–952, 1999.
[8] J. Dongarra, J. Du Croz, I. S. Duff, and S. Hammarling. A Set of Level 3 Basic Linear Algebra
Subprograms. ACM Trans. Math. Soft., 16:1–17, 1990.
[9] J. Dongarra, J. Du Croz, S. Hammarling, and Richard J. Hanson. An Extended Set of FOR-
TRAN Basic Linear Algebra Subprograms. ACM Trans. Math. Soft., 14(1):1–17, March 1988.
[10] I. S. Duff and J. Koster. The design and use of algorithms for permuting large entries to the
diagonal of sparse matrices. SIAM J. Matrix Analysis and Applications, 20(4):889–901, 1999.
[11] I. S. Duff and J. Koster. On algorithms for permuting large entries to the diagonal of a sparse
matrix. SIAM J. Matrix Analysis and Applications, 22(4):973–996, 2001.
[12] I.S. Duff, R.G. Grimes, and J.G. Lewis. Users’ guide for the Harwell-Boeing sparse matrix col-
lection (release 1). Technical Report RAL-92-086, Rutherford Appleton Laboratory, December
1992.
77
[13] A. George, J. Liu, and E. Ng. A data structure for sparse QR and LU factorizations. SIAM
J. Sci. Stat. Comput., 9:100–121, 1988.
[14] A. George and E. Ng. Symbolic factorization for sparse Gaussian elimination with partial
pivoting. SIAM J. Sci. Stat. Comput., 8(6):877–898, 1987.
[15] J. R. Gilbert, X. S. Li, E. G. Ng, and B. W. Peyton. Computing row and column counts for
sparse QR and LU factorization. BIT, 41(4):693–710, 2001.
[16] John R. Gilbert and Esmond G. Ng. Predicting structure in nonsymmetric sparse matrix
factorizations. In A. George, J. R. Gilbert, and J. W. H. Liu, editors, Graph theory and sparse
matrix computation, pages 107–139. Springer-Verlag, New York, 1993.
[17] L. Grigori, J. W. Demmel, and X. S. Li. Parallel symbolic factorization for sparse LU with
static pivoting. SIAM J. Scientific Computing, 29(3):1289–1314, 2007.
[18] B. Hendrickson and R. Leland. The CHACO’s User’s Guide. Technical Report SAND95-
2344•UC-405, Sandia National Laboratories, Albuquerque, 1995. [Link]
gov/~bahendr/[Link].
[19] N. J. Higham. Accuracy and Stability of Numerical Algorithms. SIAM, Philadelphia, PA, 1996.
[20] G. Karypis and V. Kumar. MeTiS – serial graph partitioning and computing fill-reducing ma-
trix ordering. University of Minnesota. [Link]
[21] G. Karypis, K. Schloegel, and V. Kumar. ParMeTiS: Parallel graph partitioning and sparse
matrix ordering library – version 3.1. University of Minnesota, 2003. [Link]
[Link]/~karypis/metis/parmetis/.
[22] C. Lawson, R. Hanson, D. Kincaid, and F. Krogh. Basic Linear Algebra Subprograms for
Fortran usage. ACM Trans. Math. Soft., 5:308–323, 1979.
[23] X. S. Li. Sparse Gaussian elimination on high performance computers. Technical Report
UCB//CSD-96-919, Computer Science Division, U.C. Berkeley, September 1996. Ph.D disser-
tation.
[24] X. S. Li. An overview of SuperLU: Algorithms, implementation, and user interface. ACM
Trans. Mathematical Software, 31(3):302–325, September 2005.
[25] X. S. Li and J. W. Demmel. Making sparse Gaussian elimination scalable by static pivoting.
In Proceedings of SC98: High Performance Networking and Computing Conference, Orlando,
Florida, November 7–13 1998.
78
[28] J. W. H. Liu. Modification of the minimum degree algorithm by multiple elimination. ACM
Trans. Mathematical Software, 11:141–153, 1985.
[30] W. Oettli and W. Prager. Compatibility of approximate solution of linear equations with given
error bounds for coefficients and right hand sides. Num. Math., 6:405–409, 1964.
[31] F. Pellegrini. Scotch and libScotch 5.1 User’s Guide (version 5.1.11). INRIA Bordeaux
Sud-Ouest, Université Bordeaux I. November, 2010. [Link]
scotch/.
[32] POSIX System Application Arogram Interface: Threads extension [C Language], POSIX
1003.1c draft 4. IEEE Standards Department.
[33] Y. Saad. ILUT: A dual threshold incomplete LU factorization. Numerical Linear Algebra with
Applications, 1(4):387–402, 1994.
[34] P. Sao, R. Vuduc, and X. Li. A distributed CPU-GPU sparse direct solver. In Proc. of
Euro-Par 2014, LNCS Vol. 8632, pp. 487-498, Porto, Portugal, August 25-29 2014.
[35] R.D. Skeel. Iterative refinement implies numerical stability for Gaussian elimination. Mathe-
matics of Computation, 35(151):817–832, 1980.
79