[UPDATE] Updated psb_gedot test, adding a new check on global vs local computation. Also implemented some utils to support it, since multiple kernels will use this feature.

test_dev
Stack-1 10 months ago
parent 36eed9f821
commit 52c8c4edea

@ -13,41 +13,39 @@ The necessary dependnces are:
- CUDA 12.5
## Test Approach
In order to check wheter each kernel computation is correct or not, it was taken into account a simple approach resported in [[1]](#testing): the kernels are excecuted both in single $y_{s}$ and double precision $y_{d}$. The difference between the two results $\Delta y$ should not exceed the machine epsilon of the single precision floating point representation. This quantity is identified as the unit roundoff $u$. In this the IEEE floating point representation we have $$u = 2^-24 \approx 5.96 \cdot 10^{-8}$$ and therefore $$\Delta y = y_d - y_s \leq u$$ as stated in Highman in his book [[2]](#accuracy). It is also important to note that $\Delta y$ is a double precision floating point number, since it should be able to detect an higher precision with respect to a single precision representation.
In order to check wheter each kernel computation is correct or not, it was taken into account a simple approach resported in [[1]](#testing): the kernels are excecuted both in single $y_{s}$ and double precision $y_{d}$. The difference between the two results $\Delta y$ should not exceed the machine epsilon of the single precision floating point representation. This quantity is identified as the unit roundoff $u$. In this the IEEE floating point representation we have $u = 2^-24 \approx 5.96 \cdot 10^{-8}$ and therefore $\Delta y = y_d - y_s \leq u$ as stated in Highman in his book [[2]](#accuracy). It is also important to note that $\Delta y$ is a double precision floating point number, since it should be able to detect an higher precision with respect to a single precision representation.
The innovative approach introduced in this test suite is to have a theoretical results showing us the correctness of the double precision implementation. In fact, the double precision computation is used as validation result for the single precision one, but no assumption of correctness were done before. In this work, double precision computations are validated using a heuristic approach based on the number $p$ of significand digits that can be estimated using the $\gamma_n = \frac{nu}{1-nu}$ worst case constant known from Higman [[2]](#accuracy) in order to have an upper bound to the number of significand digits. Since this approach is kernel specific, see each test directory to see how this idea is applied to each routine.
## Directory description
Each directory has the name of the computational kernel routines described in the documentation of the version 3.9 of the PSBLAS library. In each directory there are different files and directories:
- parallel/
- serial/
- vectors/
- autotest.sh
- Makefile
- <routine_name>.f90
- psb_<routine_name>_test.f90
- README.md
Each directory has the name of the computational kernel routines described in the documentation of the version 3.9 of the PSBLAS library. In each directory there are different files:
- ```autotest.sh```, it's the bash script excecuting and also possibily compiling kernel specific tests.
- ```Makefile```, contains all the rules to compile the subdir including PSBLAS modules and files, also according to the PSBLAS testing environment utilities.
- ```psb_<kernel_name>_test.f90```, a single file implementing a main program that initializes the testing environment and start test routine parametrizing over the test input space. In this file it also contained a subroutine containing the call to the actual kernel using the parameters passed from the main program.
- ```README.md``, a file explaining the input space and all the choices used to validete and explain the tests implemented.
## Routines
In this test suite were considered only computational routines implemented by PSBLAS, according to the version 3.9 of the documentation. In the following table are reported all the kernels, their implementation and wheter or not they were tested yet.
|**Kernel**| **PSBLAS Subroutine**|**Description**|**Test**|
| ------------------------------- | :--------------------------: | ---------------------------------------------------------------------- | :---------------: |
|**General Dense Matrix Sum**| `psb_geaxpby`| This subroutine is an interface to the computational kernel for dense matrix sum:$$Y \leftarrow \alpha X + \beta Y$$|Yes ✅|
| **Dot product**|`psb_gedot`|This function computes dot product between two vectors x and y.$$dot \leftarrow x^T y$$If x and y are real vectors it computes dot-product as:$$dot \leftarrow x^H y$$|Work in progress :hammer_and_wrench:|
| **Generalized Dot Product** |`psb_gedots`|This subroutine computes a series of dot products among the columns of two dense matrices x and y:$$res(i) \leftarrow x(:,i)^T y(:,i)$$If the matrices are complex, then the usual convention applies, i.e. the conjugate transpose of x is used. If x and y are of rank one, then res is a scalar, else it is a rank one array.|No ❌|
|**Infinity-Norm of Vector**|`psb_normi`/`psb_geamax`|This function computes the infinity-norm of a vector x. If x is a real vector it computes infinity norm as:$$amax \leftarrow max \mid x_i \mid$$else if x is a complex vector then it computes the infinity-norm as:$$amax \leftarrow max(\mid re(x_i) \mid + \mid im(x_i) \mid)$$|No ❌|
|**Generalized Infinity Norm**|`psb_geamaxs`|This subroutine computes a series of infinity norms on the columns of a dense matrix x:$$res(i) \leftarrow max_k \mid x(k,i) \mid$$| No ❌ |
| **1-Norm of Vector**| `psb_norm1` / `psb_geasums`|This function computes the 1-norm of a vector x. If x is a real vector it computes 1-norm as:$$asum \leftarrow \mid \mid x_i \mid \mid$$else if x is a complex vector then it computes 1-norm as:$$asum \leftarrow \mid \mid re(x) \mid \mid_1 + \mid \mid im(x) \mid \mid_1$$|No ❌|
|**Generalized 1-Norm of Vector**|`psb_geasums`|This subroutine computes a series of 1-norms on the columns of a dense matrix x:$$res(i) \leftarrow max_k \mid x(k,i) \mid$$This function computes the 1-norm of a vector x. If x is a real vector it computes 1-norm as:$$res(i) \leftarrow \mid \mid x_i \mid \mid$$else if x is a complex vector then it computes 1-norm as:$$res(i) \leftarrow \mid \mid re(x) \mid \mid_\ + \mid \mid im(x) \mid \mid_1$$|No ❌|
| **2-Norm of Vector**|`psb_norm2` / `psb_genrm2`| This function computes the 2-norm of a vector x. If x is a real vector it computes 2-norm as:$$nrm2 \leftarrow \sqrt{x^T x}$$else if x is a complex vector then it computes 2-norm as:$$nrm2 \leftarrow \sqrt{x^H x}$$|No ❌|
|**Generalized 2-Norm of Vector**|`psb_genrm2s` / `psb_spnrm1` |This subroutine computes a series of 2-norms on the columns of a dense matrix x:$$res(i) \leftarrow \mid \mid x(:,i) \mid \mid_2$$|No ❌|
|**1-Norm of Sparse Matrix**|`psb_norm1`|This function computes the 1-norm of a matrix A:$$nrm1 \leftarrow \mid \mid A \mid \mid_1$$where A represents the global matrix A|No ❌|
|**Infinity Norm of Sparse Matrix**|`psb_normi` / `psb_spnrmi`|This function computes the infinity-norm of a matrix A:$$nrmi \leftarrow \mid \mid A \mid \mid_{\infty}$$where: A represents the global matrix A|No ❌|
|**Sparse Matrix by Dense Matrix Product**| `psb_spmm`|This subroutine computes the Sparse Matrix by Dense Matrix Product:$$y \leftarrow \alpha A x + \beta y$$$$y \leftarrow \alpha A^T x + \beta y$$$$y \leftarrow \alpha A^H x + \beta y$$where: <br> x is the global dense matrix x_{:,:} <br> y is the global dense matrix y_{:,:} <br> A is the global sparse matrix A|Work in progress :hammer_and_wrench:|
|**Triangular System Solve**|`psb_spsm`|This subroutine computes the Triangular System Solve:$$y \leftarrow \alpha T^{-1} x + \beta y$$$$y \leftarrow \alpha D^{-1} x + \beta y$$$$y \leftarrow \alpha T^{-1} D x + \beta y$$$$y \leftarrow \alpha T^{-T} x + \beta y$$$$y \leftarrow \alpha D T^{-T} x + \beta y$$$$y \leftarrow \alpha T^{-T} D x + \beta y$$$$y \leftarrow \alpha T^{-H} x + \beta y$$$$y \leftarrow \alpha D T^{-H} x + \beta y$$$$y \leftarrow \alpha T^{-H} D x + \beta y$$where: <br> x is the global dense matrix x_{:,:} <br> y is the global dense matrix y_{:,:} <br> T is the global sparse block triangular submatrix T <br> D is the scaling diagonal matrix|No ❌|
|**Entrywise Product**|`psb_gemlt`|This function computes the entrywise product between two vectors x and y$$dot \leftarrow x(i)y(i)$$|No ❌|
|**Entrywise Division**|`psb_gediv`|This function computes the entrywise division between two vectors x and y$$div \leftarrow \frac{x(i)}{y(i)}$$|No ❌|
|**Entrywise Inversion**|`psb_geinv`|This function computes the entrywise inverse of a vector x and puts it into y$$inv \leftarrow \frac{1}{x(i)}$$|No ❌|
|**Kernel**| **PSBLAS Subroutine**|**Description**|**Single Process Test**|**Multi-Process Test**|**Complex Test**|**GPU Test**|
| ------------------------------- | :--------------------------: | ---------------------------------------------------------------------- | :---------------: |:---------------: |:---------------: |:---------------: |
|**General Dense Matrix Sum**| `psb_geaxpby`| This subroutine is an interface to the computational kernel for dense matrix sum: $Y \leftarrow \alpha X + \beta Y$|Work in progress :hammer_and_wrench:|Work in progress :hammer_and_wrench:|No ❌|No ❌|
| **Dot product**|`psb_gedot`|This function computes dot product between two vectors x and y.$dot \leftarrow x^T y$If x and y are real vectors it computes dot-product as:$dot \leftarrow x^H y$|Yes ✅|Yes ✅|No ❌|No ❌|
| **Generalized Dot Product** |`psb_gedots`|This subroutine computes a series of dot products among the columns of two dense matrices x and y:$res(i) \leftarrow x(:,i)^T y(:,i)$If the matrices are complex, then the usual convention applies, i.e. the conjugate transpose of x is used. If x and y are of rank one, then res is a scalar, else it is a rank one array.|No ❌|No ❌|No ❌|No ❌|
|**Infinity-Norm of Vector**|`psb_normi`/`psb_geamax`|This function computes the infinity-norm of a vector x. If x is a real vector it computes infinity norm as:$amax \leftarrow max \mid x_i \mid$else if x is a complex vector then it computes the infinity-norm as:$amax \leftarrow max(\mid re(x_i) \mid + \mid im(x_i) \mid)$|No ❌|No ❌|No ❌|No ❌|
|**Generalized Infinity Norm**|`psb_geamaxs`|This subroutine computes a series of infinity norms on the columns of a dense matrix x:$res(i) \leftarrow max_k \mid x(k,i) \mid$|No ❌|No ❌|No ❌|No ❌|
| **1-Norm of Vector**| `psb_norm1` / `psb_geasums`|This function computes the 1-norm of a vector x. If x is a real vector it computes 1-norm as:$asum \leftarrow \mid \mid x_i \mid \mid$else if x is a complex vector then it computes 1-norm as:$asum \leftarrow \mid \mid re(x) \mid \mid_1 + \mid \mid im(x) \mid \mid_1$|No ❌|No ❌|No ❌|No ❌|
|**Generalized 1-Norm of Vector**|`psb_geasums`|This subroutine computes a series of 1-norms on the columns of a dense matrix x:$res(i) \leftarrow max_k \mid x(k,i) \mid$This function computes the 1-norm of a vector x. If x is a real vector it computes 1-norm as:$res(i) \leftarrow \mid \mid x_i \mid \mid$else if x is a complex vector then it computes 1-norm as:$res(i) \leftarrow \mid \mid re(x) \mid \mid_\ + \mid \mid im(x) \mid \mid_1$|No ❌|No ❌|No ❌|No ❌|
| **2-Norm of Vector**|`psb_norm2` / `psb_genrm2`| This function computes the 2-norm of a vector x. If x is a real vector it computes 2-norm as:$nrm2 \leftarrow \sqrt{x^T x}$else if x is a complex vector then it computes 2-norm as:$nrm2 \leftarrow \sqrt{x^H x}$|No ❌|No ❌|No ❌|No ❌|
|**Generalized 2-Norm of Vector**|`psb_genrm2s` / `psb_spnrm1` |This subroutine computes a series of 2-norms on the columns of a dense matrix x:$res(i) \leftarrow \mid \mid x(:,i) \mid \mid_2$|No ❌|No ❌|No ❌|No ❌|
|**1-Norm of Sparse Matrix**|`psb_norm1`|This function computes the 1-norm of a matrix A:$nrm1 \leftarrow \mid \mid A \mid \mid_1$where A represents the global matrix A|No ❌|No ❌|No ❌|No ❌|
|**Infinity Norm of Sparse Matrix**|`psb_normi` / `psb_spnrmi`|This function computes the infinity-norm of a matrix A:$nrmi \leftarrow \mid \mid A \mid \mid_{\infty}$where: A represents the global matrix A|No ❌|No ❌|No ❌|No ❌|
|**Sparse Matrix by Dense Matrix Product**| `psb_spmm`|This subroutine computes the Sparse Matrix by Dense Matrix Product:$y \leftarrow \alpha A x + \beta y$$y \leftarrow \alpha A^T x + \beta y$$y \leftarrow \alpha A^H x + \beta y$where: <br> x is the global dense matrix x_{:,:} <br> y is the global dense matrix y_{:,:} <br> A is the global sparse matrix A|Work in progress :hammer_and_wrench:|No ❌|No ❌|No ❌|
|**Triangular System Solve**|`psb_spsm`|This subroutine computes the Triangular System Solve:$y \leftarrow \alpha T^{-1} x + \beta y$$y \leftarrow \alpha D^{-1} x + \beta y$$y \leftarrow \alpha T^{-1} D x + \beta y$$y \leftarrow \alpha T^{-T} x + \beta y$$y \leftarrow \alpha D T^{-T} x + \beta y$$y \leftarrow \alpha T^{-T} D x + \beta y$$y \leftarrow \alpha T^{-H} x + \beta y$$y \leftarrow \alpha D T^{-H} x + \beta y$$y \leftarrow \alpha T^{-H} D x + \beta y$where: <br> x is the global dense matrix x_{:,:} <br> y is the global dense matrix y_{:,:} <br> T is the global sparse block triangular submatrix T <br> D is the scaling diagonal matrix|No ❌|No ❌|No ❌|No ❌|
|**Entrywise Product**|`psb_gemlt`|This function computes the entrywise product between two vectors x and y$dot \leftarrow x(i)y(i)$|No ❌|No ❌|No ❌|No ❌|
|**Entrywise Division**|`psb_gediv`|This function computes the entrywise division between two vectors x and y$div \leftarrow \frac{x(i)}{y(i)}$|No ❌|No ❌|No ❌|No ❌|
|**Entrywise Inversion**|`psb_geinv`|This function computes the entrywise inverse of a vector x and puts it into y$inv \leftarrow \frac{1}{x(i)}$|No ❌|No ❌|No ❌|No ❌|
## Developer Notes
In order to keep compliant the excecution of the bash script used to automate the teest excecution, remember to create a new directory to put new tests and to use the name convention of psb_test_ signature for utilities functions and psb_kernel_test for tests used for new routines.

@ -1,14 +1,13 @@
COMPLETED:
- Try to use Julienne https://github.com/berkeleylab/julienne in order to avoid different do nested loops [OK]
(Possible solutions are to use Fortuno and FPunit, in order to implement parametrized tests)
- Remove file generation in order to save up memory [OK]
- Clean main log at each run [OK] (Log aggregation was deleted)
- Fix log aggregation in main directory, see number of total tests [OK] (Log aggregation was deleted)
TODO:
- Remove file generation in order to save up memory (Is it necessary for single/multiple processes comparison, it should be removed as a cleanup)
- Fix parallel and serial, using a fortran routine instead of the diff between files
- Fix log aggregation in main directory, see number of total tests (EG. 144 instead of 16 in gedot)
- Clean main log at each run
- Force recompilation in main script
- What about multiple distribution for psb_gedot?
- Generate input vectors only if vectors/ directory doesn't exist to save up time
- Force recompilation in main script (A flag should be added)
- Generate input vectors only if vectors/ directory doesn't exist to save up time (It is really dependant on the kernel analyzed, it is not always possible)

@ -64,7 +64,3 @@ The results of the computation will be saved on different files based on the ins
- Test also GPU excecution
- Try multiple distributions
- Fix result_check handling, it should not be an entire vector
## Notes
5.96e-08 is 2^-24 (Single precision unit roundoff), 1.19e-07 is 2^-23 (Single precision unit interval)

@ -87,8 +87,6 @@ program main
implicit none
! Communicator variable
type(psb_ctxt_type) :: ctxt
@ -96,15 +94,16 @@ program main
character(len=64) :: x(4),y(4)
integer(psb_ipk_) :: arr_size
integer(psb_ipk_) :: tests_number, count
logical :: global(2) = [.true., .false.]
! cycle indexes variables
integer(psb_ipk_) :: i,j,k,h,l
integer(psb_ipk_) :: info, unit
! results
real(psb_spk_) :: result_single
real(psb_spk_) :: result_single, global_result_single
real(psb_dpk_) :: result_double
type(test_info_) :: test_info
type(psb_test_info) :: test_info
@ -122,7 +121,7 @@ program main
arr_size = 100000
!! Initialize test metadata
test_info%total_tests = size(x) * size(y)
test_info%total_tests = size(x) * size(y) * size(global)
test_info%threshold_type = GAMMA
test_info%threshold = 0.0
test_info%kernel_name = "psb_gedot"
@ -143,19 +142,26 @@ program main
! Iterate over test parameters
do i=1,size(x)
do j=1,size(y)
call psb_gedot_real_kernel(x(i), y(j), arr_size, test_info%ctxt, result_single, result_double)
if(test_info%my_rank == psb_root_) then
call psb_test_single_double_check(result_single,result_double,test_info, arr_size)
test_info%current_test = test_info%current_test + 1
end if
call psb_barrier(test_info%ctxt)
do h=1,size(global)
call psb_gedot_real_kernel(x(i), y(j), arr_size, test_info%ctxt,global(h), result_single, result_double)
if(test_info%my_rank == psb_root_) then
if(global(h) .eqv. .true.) then
global_result_single = result_single
call psb_test_single_double_check(result_single,result_double,test_info, arr_size)
else
call psb_test_check_global_local(global_result_single, result_single, test_info)
end if
test_info%current_test = test_info%current_test + 1
end if
call psb_barrier(test_info%ctxt)
end do
end do
end do
call psb_test_exit(test_info)
contains
!> @brief Function to excecute psb_gedot in single precision real
@ -168,12 +174,14 @@ contains
!! @param ctxt communication context
!! @param result_single result of the single precision computation
!! @param result_double result of the double precision computation
!! @param global if .true. the result is a global reduction, otherwise it is local
!!
subroutine psb_gedot_real_kernel(x_file, y_file, arr_size, ctxt, result_single, result_double)
subroutine psb_gedot_real_kernel(x_file, y_file, arr_size, ctxt, global, result_single, result_double)
! input parameters
character(len = *), intent(in) :: x_file, y_file
integer(psb_ipk_), intent(in) :: arr_size
type(psb_ctxt_type), intent(in) :: ctxt
logical, intent(in) :: global
! output parameters
real(psb_spk_), intent(out) :: result_single
@ -284,19 +292,27 @@ contains
end if
! y = x^T * y
result_single = psb_gedot(x_single,y_single,desc_a,info)
result_single = psb_gedot(x_single,y_single,desc_a,info,global)
if(info /= psb_success_) then
write(psb_out_unit,'(A)') "Error in psb_gedot routine in single precision"
goto 9999
end if
result_double = psb_gedot(x_double,y_double,desc_a,info)
result_double = psb_gedot(x_double,y_double,desc_a,info,global)
if(info /= psb_success_) then
write(psb_out_unit,'(A)') "Error in psb_gedot routine in double precision"
goto 9999
end if
if(global .eqv. .false.) then
! If the result is local, we need to sum the local results
! to get the final result
call psb_sum(ctxt, result_single)
call psb_sum(ctxt, result_double)
end if
! Deallocate
9999 call psb_gefree(x_single, desc_a,info)
if(info /= psb_success_) then

@ -12,7 +12,7 @@
!! @param test_info is a data structure containing all the metadata usefull for test output
!!
subroutine psb_test_log_passed(test_info)
type(test_info_), intent(in) :: test_info
type(psb_test_info), intent(in) :: test_info
! time stats variables
character(len=8) :: date
character(len=10) :: time
@ -34,7 +34,7 @@ end subroutine
!! @param test_info is a data structure containing all the metadata usefull for test output
!!
subroutine psb_test_log_failed(test_info)
type(test_info_), intent(in) :: test_info
type(psb_test_info), intent(in) :: test_info
! time stats variables
character(len=8) :: date
character(len=10) :: time
@ -57,7 +57,7 @@ end subroutine
!! @param test_info is a data structure containing all the metadata usefull for test output
!!
subroutine psb_test_progress_bar(test_info)
type(test_info_), intent(in) :: test_info
type(psb_test_info), intent(in) :: test_info
integer(psb_ipk_) :: percent, bar_width, num_hashes, num_spaces
character(len=100) :: bar

@ -19,22 +19,24 @@ module psb_test_utils
implicit none
! Define the enumeration values to represent testing criteria
integer, parameter :: DEFAULT = -1
integer, parameter :: VALUE = 1
integer, parameter :: GAMMA = 2
! Define test metadata struct
type :: test_info_
type :: psb_test_info
integer(psb_ipk_) :: current_test = 1 !> The test that is currently beeing run
integer(psb_ipk_) :: total_tests = 1 !> The number of the total tests to run
integer(psb_ipk_) :: success = 0 !> the number of tests that succeded
integer(psb_ipk_) :: failure = 0 !> The number of tests that failed
integer(psb_ipk_) :: output_unit = 6 !> The output file handles (stdout by default)
character(len=32) :: kernel_name = "unknown" !> The PSBLAS kernel that is beeing tested
integer(psb_ipk_) :: threshold_type = VALUE !> The criteria used to pass a test (VAL,...)
character(len=32) :: kernel_name = "default" !> The PSBLAS kernel that is beeing tested
integer(psb_ipk_) :: threshold_type = DEFAULT !> The criteria used to pass a test (VAL,...)
real(psb_dpk_) :: threshold = 0.0 !> The threashold value used for acceptance
type(psb_ctxt_type) :: ctxt !> The PSBLAS context (Used for MPI communications)
integer(psb_ipk_) :: my_rank = 0 !> The rank of the current process in the MPI communicator
end type test_info_
integer(psb_ipk_) :: mat_dist = DEFAULT !> The distribution of the matrix (default is block row distribution)
end type psb_test_info
contains
@ -47,10 +49,10 @@ contains
!! @param test_info The test information structure to be initialized.
!!
subroutine psb_test_init(test_info)
type(test_info_), intent(inout) :: test_info
integer(psb_ipk_) :: output_unit, info
type(psb_test_info), intent(inout) :: test_info
integer(psb_ipk_) :: output_unit, info
! MPI variables
integer(psb_ipk_) :: my_rank, np
integer(psb_ipk_) :: my_rank, np
call psb_init(test_info%ctxt)
@ -62,9 +64,6 @@ contains
call psb_exit(test_info%ctxt)
end if
! Set the output unit based on the number of processes
! Set the output unit to stdout by default
if(np == 1) then
open(newunit=output_unit, file=trim(test_info%kernel_name)//'_test.log', &
@ -79,7 +78,7 @@ contains
write(*, '(A,I0)') "Error opening log file for kernel ", test_info%kernel_name
write(*, '(A,I0)') "I/O Status Code:", info
write(*, '(A)') "Please check if the file is accessible and writable."
call psb_exit(test_info%ctxt)
call psb_test_exit(test_info)
end if
test_info%output_unit = output_unit
@ -89,6 +88,36 @@ contains
write(test_info%output_unit,'(A,I0)') 'Number of processes used in this computation: ', np
write(test_info%output_unit,'(A)') ''
! Check if the kernel name is set to default
if(test_info%kernel_name == "default") then
write(test_info%output_unit,'(A)') "Warning: Kernel name is not set. Using default kernel name 'default'."
else
write(test_info%output_unit,'(A)') "Kernel name set to: " // trim(test_info%kernel_name)
end if
! Check the threshold type and value
if(test_info%mat_dist == DEFAULT) then
write(test_info%output_unit,'(A)') "Matrix distribution set to default (block row distribution)."
else
write(test_info%output_unit,'(A,I0)') "Matrix distribution set to: ", test_info%mat_dist
end if
! Check the threshold type and value
if(test_info%threshold_type == DEFAULT) then
write(test_info%output_unit,'(A,F20.10)') "Threshold type is set to default. &
& using single precision IEEE unit roundoff as threshould ", 5.96D-08
else if(test_info%threshold_type == VALUE) then
write(test_info%output_unit,'(A,F20.10)') "Threshold type is set to VALUE, so absolute error will be checked &
& using threshold: ", test_info%threshold
else if(test_info%threshold_type == GAMMA) then
write(test_info%output_unit,'(A)') "Threshold type is set to GAMMA, so relative error will be checked"
else
write(test_info%output_unit,'(A,I0)') "Error: Invalid threshold type: ", test_info%threshold_type
call psb_test_exit(test_info)
end if
write(test_info%output_unit,'(A)') ''
end subroutine
!> @brief Function to finalize the test environment, it is used to close the output unit
@ -97,8 +126,8 @@ contains
!! @param test_info The test information structure to be finalized.
!!
subroutine psb_test_exit(test_info)
type(test_info_), intent(inout) :: test_info
integer(psb_ipk_) :: info
type(psb_test_info), intent(inout) :: test_info
integer(psb_ipk_) :: info
! Finalize test
if(test_info%my_rank == psb_root_) then
@ -134,7 +163,7 @@ contains
!! @param arr_size The size of the array to be used for validation.
!!
function psb_test_validate(result_single, result_double, test_info, arr_size) result(pass)
type(test_info_) :: test_info
type(psb_test_info) :: test_info
real(psb_spk_) :: result_single
real(psb_dpk_) :: result_double
integer(psb_ipk_) :: arr_size,int_digits
@ -316,7 +345,7 @@ contains
real(psb_spk_), intent(inout) :: result_single
real(psb_dpk_), intent(inout) :: result_double
real(psb_dpk_) :: delta
type(test_info_), intent(inout) :: test_info
type(psb_test_info), intent(inout) :: test_info
call psb_test_progress_bar(test_info)
@ -334,7 +363,33 @@ contains
end if
end subroutine
!!
!> @brief Subroutine to check the global and local results of a single precision computation.
!! It compares the global result with the local result and logs the outcome.
!!
!! @param global_result_single The global single precision result to be checked.
!! @param result_single The local single precision result to be checked.
!! @param test_info The test information structure containing the logging details.
!!
subroutine psb_test_check_global_local(global_result_single, result_single, test_info)
real(psb_spk_), intent(in) :: global_result_single,result_single
type(psb_test_info) :: test_info
call psb_test_progress_bar(test_info)
! Check if the global result is equal to the local result
if (global_result_single == result_single) then
call psb_test_log_passed(test_info)
test_info%success = test_info%success + 1
else
call psb_test_log_failed(test_info)
write(test_info%output_unit,'(A,F20.10)') "Global single precision result: ", global_result_single
write(test_info%output_unit,'(A,F20.10)') "Local single precision result: ", result_single
test_info%failure = test_info%failure + 1
end if
end subroutine
!! subroutine psb_parallel_check()
!!
!! end subroutine

Loading…
Cancel
Save