Skip to content

Commit

Permalink
rocSPARSE preconditioner csrilu0 example
Browse files Browse the repository at this point in the history
  • Loading branch information
Beanavil authored and Naraenda committed Oct 19, 2023
1 parent 158c3a6 commit d6b4446
Show file tree
Hide file tree
Showing 20 changed files with 1,007 additions and 3 deletions.
1 change: 1 addition & 0 deletions Libraries/rocSPARSE/preconditioner/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,4 @@ project(rocSPARSE_preconditioner_examples LANGUAGES NONE)
add_subdirectory(bsric0)
add_subdirectory(bsrilu0)
add_subdirectory(csric0)
add_subdirectory(csrilu0)
3 changes: 2 additions & 1 deletion Libraries/rocSPARSE/preconditioner/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@
EXAMPLES := \
bsric0 \
bsrilu0 \
csric0
csric0 \
csrilu0

all: $(EXAMPLES)

Expand Down
4 changes: 2 additions & 2 deletions Libraries/rocSPARSE/preconditioner/bsrilu0/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -266,9 +266,9 @@ int main()
// L matrix is stored in the lower part of A. The diagonal is not stored as it is known
// that all the diagonal elements are the multiplicative identity (1 in this case).
const double eps = 1.0e5 * std::numeric_limits<double>::epsilon();
for(int i = 0; i < n; ++i)
for(rocsparse_int i = 0; i < n; ++i)
{
for(int j = 0; j < n; ++j)
for(rocsparse_int j = 0; j < n; ++j)
{
const double val = (j < i) ? A[j * n + i] : (j == i);
std::cout << std::setw(3) << val;
Expand Down
62 changes: 62 additions & 0 deletions Libraries/rocSPARSE/preconditioner/csrilu0/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# MIT License
#
# Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

set(example_name rocsparse_csrilu0)

cmake_minimum_required(VERSION 3.21 FATAL_ERROR)
project(${example_name} LANGUAGES CXX)

if(GPU_RUNTIME STREQUAL "CUDA")
message(STATUS "rocSPARSE examples do not support the CUDA runtime")
return()
endif()

# This example does not contain device code, thereby it can be compiled with any conforming C++ compiler.

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

if(WIN32)
set(ROCM_ROOT "$ENV{HIP_PATH}" CACHE PATH "Root directory of the ROCm installation")
else()
set(ROCM_ROOT "/opt/rocm" CACHE PATH "Root directory of the ROCm installation")
endif()

list(APPEND CMAKE_PREFIX_PATH "${ROCM_ROOT}")

find_package(rocsparse REQUIRED)

add_executable(${example_name} main.cpp)
# Make example runnable using ctest
add_test(${example_name} ${example_name})

# Link to example library
target_link_libraries(${example_name} PRIVATE roc::rocsparse hip::host)

target_include_directories(${example_name} PRIVATE "../../../../Common")

install(TARGETS ${example_name})

if(CMAKE_SYSTEM_NAME MATCHES Windows)
install(IMPORTED_RUNTIME_ARTIFACTS roc::rocsparse)
endif()
58 changes: 58 additions & 0 deletions Libraries/rocSPARSE/preconditioner/csrilu0/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# MIT License
#
# Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

EXAMPLE := rocsparse_csrilu0
COMMON_INCLUDE_DIR := ../../../../Common
GPU_RUNTIME := HIP

ifneq ($(GPU_RUNTIME), HIP)
$(error GPU_RUNTIME is set to "$(GPU_RUNTIME)". GPU_RUNTIME must be HIP.)
endif

ROCM_INSTALL_DIR := /opt/rocm

HIP_INCLUDE_DIR := $(ROCM_INSTALL_DIR)/include
ROCSPARSE_INCLUDE_DIR := $(HIP_INCLUDE_DIR)

CXX ?= g++

# Common variables and flags
CXX_STD := c++17
ICXXFLAGS := -std=$(CXX_STD)
ICPPFLAGS := -isystem $(ROCSPARSE_INCLUDE_DIR) -isystem $(HIP_INCLUDE_DIR) -I $(COMMON_INCLUDE_DIR) -D__HIP_PLATFORM_AMD__
ILDFLAGS := -L $(ROCM_INSTALL_DIR)/lib
ILDLIBS := -lrocsparse -lamdhip64

CXXFLAGS ?= -Wall -Wextra

ICXXFLAGS += $(CXXFLAGS)
ICPPFLAGS += $(CPPFLAGS)
ILDFLAGS += $(LDFLAGS)
ILDLIBS += $(LDLIBS)

$(EXAMPLE): main.cpp $(COMMON_INCLUDE_DIR)/example_utils.hpp $(COMMON_INCLUDE_DIR)/rocsparse_utils.hpp
$(CXX) $(ICXXFLAGS) $(ICPPFLAGS) $(ILDFLAGS) -o $@ $< $(ILDLIBS)

clean:
$(RM) $(EXAMPLE)

.PHONY: clean
122 changes: 122 additions & 0 deletions Libraries/rocSPARSE/preconditioner/csrilu0/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
# rocSPARSE Preconditioner CSR Incomplete LU Decomposition Example

## Description
This example illustrates the use of the `rocSPARSE` incomplete LU factorization preconditioner using the CSR storage format.

Given an arbitrary matrix $A$ of order $n$, computing its LU decomposition consists of finding a lower triangular matrix $L$ and a upper triangular matrix $U$ such that
$$A = L \cdot U.$$

The _incomplete_ LU decomposition is a sparse approximation of the above-mentioned LU decomposition. Thus, `rocSPARSE` allows us to compute a sparse lower triangular matrix $L$ and a sparse upper triangular matrix $U$ such that
$$A \approx L \cdot U.$$

### Application flow
1. Set up input data.
2. Allocate device memory and offload input data to the device.
3. Initialize rocSPARSE by creating a handle.
4. Prepare utility variables for rocSPARSE csrilu0 invocation.
5. Perform the analysis step.
6. Call dcsrilu0 to compute the incomplete LU decomposition.
7. Check zero-pivots.
8. Convert the resulting CSR sparse matrix to a dense matrix. Check and print the resulting matrix.
9. Free rocSPARSE resources and device memory.
10. Print validation result.

## Key APIs and Concepts
### CSR Matrix Storage Format
The [Compressed Sparse Row (CSR) storage format](https://rocsparse.readthedocs.io/en/latest/usermanual.html#csr-storage-format) describes an $m \times n$ sparse matrix with three arrays.

Defining
- `m`: number of rows
- `n`: number of columns
- `nnz`: number of non-zero elements

we can describe a sparse matrix using the following arrays:
- `csr_val`: array storing the non-zero elements of the matrix.
- `csr_row_ptr`: given $i \in [0, m]$
- if $` 0 \leq i < m `$, `csr_row_ptr[i]` stores the index of the first non-zero element in row $i$ of the matrix
- if $i = m$, `csr_row_ptr[i]` stores `nnz`.

This way, row $j \in [0, m)$ contains the non-zero elements of indices from `csr_row_ptr[j]` to `csr_row_ptr[j+1]-1`. Therefore, the corresponding values in `csr_val` can be accessed from `csr_row_ptr[j]` to `csr_row_ptr[j+1]-1`.
- `csr_col_ind`: given $i \in [0, nnz-1]$, `csr_col_ind[i]` stores the column of the $i^{th}$ non-zero element in the matrix.

The CSR matrix is sorted by column indices in the same row, and each pair of indices appear only once.

For instance, consider a sparse matrix as

$$
A=
\left(
\begin{array}{ccccc}
1 & 2 & 0 & 3 & 0 \\
0 & 4 & 5 & 0 & 0 \\
6 & 0 & 0 & 7 & 8
\end{array}
\right)
$$

Therefore, the CSR representation of $A$ is:

```
m = 3
n = 5
nnz = 8
csr_val = { 1, 2, 3, 4, 5, 6, 7, 8 }
csr_row_ptr = { 0, 3, 5, 8 }
csr_col_ind = { 0, 1, 3, 1, 2, 0, 3, 4 }
```

### rocSPARSE
- rocSPARSE is initialized by calling `rocsparse_create_handle(rocsparse_handle*)` and is terminated by calling `rocsparse_destroy_handle(rocsparse_handle)`.
- `rocsparse_mat_descr descr`: holds all properties of a matrix. The properties set in this example are the following:
- `rocsparse_fill_mode`: indicates whether a (triangular) matrix is lower (`rocsparse_fill_mode_lower`) or upper (`rocsparse_fill_mode_upper`) triangular.
- `rocsparse_solve_policy policy`: specifies the policy to follow for triangular solvers and factorizations. The only value accepted is `rocsparse_solve_policy_auto`.
- `rocsparse_analysis_policy analysis`: specifies the policy to follow for analysis data. The following values are accepted:
- `rocsparse_analysis_policy_reuse`: the analysis data gathered is re-used.
- `rocsparse_analysis_policy_force`: the analysis data will be re-built.
- `rocsparse_[sdcz]csrilu0` computes the incomplete LU factorization of a sparse CSR matrix $A$, such that $A \approx L \cdot U$. The correct function signature should be chosen based on the datatype of the input matrix:
- `s` single-precision real (`float`)
- `d` double-precision real (`double`)
- `c` single-precision complex (`rocsparse_float_complex`)
- `z` double-precision complex (`rocsparse_double_complex`)
- `rocsparse_[sdcz]csrilu0_analysis` performs the analysis step for `rocsparse_[sdcz]csrilu0`. The character matched in `[sdcz]` coincides with the one matched in `rocsparse_[sdcz]csrilu0`.
- `rocsparse_[sdcz]csrilu0_buffer_size` allows to obtain the size (in bytes) of the temporary storage buffer required for the `rocsparse_[sdcz]csrilu0_analysis` and `rocsparse_[sdcz]csrilu0` functions. The character matched in `[sdcz]` coincides with the one matched in any of the mentioned functions.
- `rocsparse_csrilu0_zero_pivot(rocsparse_handle, rocsparse_mat_info, rocsparse_int *position)` returns `rocsparse_status_zero_pivot` if either a structural or numerical zero has been found during the execution of `rocsparse_[sbcz]csrilu0(....)` and stores in `position` the index $i$ of the first zero pivot $A_{ii}$ found. If no zero pivot is found it returns `rocsparse_status_success`.

## Demonstrated API Calls

### rocSPARSE
- `rocsparse_analysis_policy`
- `rocsparse_analysis_policy_reuse`
- `rocsparse_csrilu0_zero_pivot`
- `rocsparse_create_handle`
- `rocsparse_create_mat_descr`
- `rocsparse_create_mat_info`
- `rocsparse_dcsrilu0`
- `rocsparse_dcsrilu0_analysis`
- `rocsparse_dcsrilu0_buffer_size`
- `rocsparse_dcsr2dense`
- `rocsparse_destroy_handle`
- `rocsparse_destroy_mat_descr`
- `rocsparse_destroy_mat_info`
- `rocsparse_fill_mode_lower`
- `rocsparse_handle`
- `rocsparse_int`
- `rocsparse_mat_descr`
- `rocsparse_mat_info`
- `rocsparse_set_mat_fill_mode`
- `rocsparse_solve_policy`
- `rocsparse_solve_policy_auto`
- `rocsparse_status`
- `rocsparse_status_zero_pivot`

### HIP runtime
- `hipFree`
- `hipMalloc`
- `hipMemcpy`
- `hipMemcpyDeviceToHost`
- `hipMemcpyHostToDevice`
24 changes: 24 additions & 0 deletions Libraries/rocSPARSE/preconditioner/csrilu0/csrilu0_vs2017.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.33026.149
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "csrilu0_vs2017", "csrilu0_vs2017.vcxproj", "{5FAE3496-9B40-4BAC-92B3-4AF9508DEC23}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{5FAE3496-9B40-4BAC-92B3-4AF9508DEC23}.Debug|x64.ActiveCfg = Debug|x64
{5FAE3496-9B40-4BAC-92B3-4AF9508DEC23}.Debug|x64.Build.0 = Debug|x64
{5FAE3496-9B40-4BAC-92B3-4AF9508DEC23}.Release|x64.ActiveCfg = Release|x64
{5FAE3496-9B40-4BAC-92B3-4AF9508DEC23}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {683B0C08-8957-4141-B99A-8824C08146C0}
EndGlobalSection
EndGlobal
Loading

0 comments on commit d6b4446

Please sign in to comment.