Commit 9ed892af authored by Pavel Kus's avatar Pavel Kus

Python plotting tool for displaying matrices introduced

Introducing python script plot.py containing several classes used to
plot matrices stored in block-cyclic distribution as a 1 global matrix.
Docstrings in plot.py should explain the ussage. There are also two
use cases included, both with commented scripts (using classes from
plot.py) and a screenshot. One of the use cases contains also tarball
with data.

Apart from that, a VERY simple module matrix_plot.F90 was created. It
is really simplistic, a more systematic approach towards loging should
be designed. At the moment, matrix output has to be triggered explicitly
in the code by calling a macro SAVE_MATR(event_description, iteration).
parent 73278966
......@@ -60,6 +60,7 @@ libelpa@SUFFIX@_private_la_SOURCES = \
src/elpa2/qr/elpa_pdgeqrf.F90 \
src/elpa1/elpa1.F90 \
src/elpa2/elpa2.F90 \
src/helpers/matrix_plot.F90 \
src/elpa_c_interface.c \
src/elpa_index.c
......
......@@ -83,6 +83,15 @@
!>
#include "../general/sanity.X90"
#undef SAVE_MATR
#ifdef DOUBLE_PRECISION_REAL
#define SAVE_MATR(name, iteration) \
call prmat(na,useGpu,a_mat,a_dev,lda,matrixCols,nblk,my_prow,my_pcol,np_rows,np_cols,name,iteration)
#else
#define SAVE_MATR(name, iteration)
#endif
subroutine tridiag_&
&MATH_DATATYPE&
&_&
......@@ -92,6 +101,7 @@
use iso_c_binding
use precision
use elpa_abstract_impl
use matrix_plot
implicit none
class(elpa_abstract_impl_t), intent(inout) :: obj
integer(kind=ik), intent(in) :: na, lda, nblk, matrixCols, mpi_comm_rows, mpi_comm_cols
......@@ -446,6 +456,8 @@
! add tau after the end of actuall v_row, to be broadcasted with it
v_row(l_rows+1) = tau(istep)
endif !(my_pcol == pcol(istep, nblk, np_cols))
! SAVE_MATR("HH vec stored", na - istep + 1)
#ifdef WITH_MPI
! Broadcast the Householder Vector (and tau) along columns
......@@ -1025,3 +1037,5 @@
&MATH_DATATYPE&
&_&
&PRECISION
\ No newline at end of file
#define REAL_DATATYPE rk8
! module for producing matrix traces, to be plotted by provided python ploter
! currently the module is very simple and non-flexible
! it is only ussable for printing the matrix A and possibly its counterpart A_DEV
! both are assumed to be in block-cyclic distribution
! At the moment, the output works for double real only
! To simplify thihngs, a conveninece macro (as follows) can be placed to .X90 template file:
! #undef SAVE_MATR
! #ifdef DOUBLE_PRECISION_REAL
! #define SAVE_MATR(name, iteration) \
! call prmat(na,useGpu,a_mat,a_dev,lda,matrixCols,nblk,my_prow,my_pcol,np_rows,np_cols,name,iteration)
! #else
! #define SAVE_MATR(name, iteration)
! #endif
! traces are stored into directory "matrices", that has to be created
module matrix_plot
contains
subroutine prmat(na, useGpu, a_mat, a_dev, lda, matrixCols, nblk, my_prow, my_pcol, np_rows, np_cols, name, iteration)
use cuda_functions
use iso_c_binding
use precision
implicit none
integer, parameter :: out_unit=20
character(len = 1025) :: directory = "matrices"
character(len = 1024) :: filename
character(len = *), intent(in) :: name
integer(kind=ik), intent(in) :: na, lda, nblk, matrixCols, my_prow, my_pcol, np_rows, np_cols, iteration
real(kind=REAL_DATATYPE), intent(in) :: a_mat(lda,matrixCols)
integer(kind=C_intptr_T), intent(in) :: a_dev
logical, intent(in) :: useGPU
integer(kind=ik) :: row, col, mpi_rank
integer(kind=ik), save :: counter = 0
real(kind=REAL_DATATYPE) :: a_dev_helper(lda,matrixCols)
logical :: successCUDA
integer(kind=c_size_t), parameter :: size_of_datatype = size_of_double_real
mpi_rank = np_rows * my_pcol + my_prow
! print a_mat
write(filename, "(A,A,I0.4,A,I0.2,A)"), trim(directory), "/a_mat-", counter, "-", mpi_rank, ".txt"
write(*,*), trim(filename)
open(unit=out_unit, file=trim(filename), action="write",status="replace")
write(out_unit, "(9I5)") na, nblk, lda, matrixCols, my_prow, my_pcol, np_rows, np_cols, iteration
write(out_unit, "(A)") name
do row = 1, lda
write(out_unit, *) a_mat(row, :)
end do
close(out_unit)
! print a_dev
if(useGpu) then
successCUDA = cuda_memcpy(loc(a_dev_helper(1,1)), a_dev, lda * matrixCols * size_of_datatype, cudaMemcpyDeviceToHost)
write(filename, "(A,A,I0.4,A,I0.2,A)"), trim(directory), "/a_dev-", counter, "-", mpi_rank, ".txt"
write(*,*), trim(filename)
open(unit=out_unit, file=trim(filename), action="write",status="replace")
write(out_unit, "(9I5)") na, nblk, lda, matrixCols, my_prow, my_pcol, np_rows, np_cols, iteration
write(out_unit, "(A)") name
do row = 1, lda
write(out_unit, *) a_dev_helper(row, :)
end do
close(out_unit)
end if
counter = counter + 1
end subroutine
end module
\ No newline at end of file
# Sample script showing a use case of ELPA matrix output for debugging
# In this case, we wanted to compare matrices for GPU and CPU variant of the code
# This feature is only experimental and will probably change
# The recomanded ussage is the following. Go to the directory of this script and run:
# ipython -i ../plot.py
# than run within python the command:
# run -i script.py
# Now a window with the plot should be created. Rearange your windows such that you can
# see both console and plot and iterate using the iterators, change views or create new, etc.
# If you want to modify this file and re-run it without closing the plotting window, comment
# out the two following lines. If you do not want to reload the data, comment out creating of
# traces.
# data traces are too large for this example and are not included
# create new matplotlib figure and pass it to the Plotter
fig = plt.figure()
pl = Plotter(fig)
# load two traces, one from a run with GPU enabled, one without
# note that this might take a lot of time, so if we have allready run this script and than only
# changed something in the following, we might choose to comment out the following commands
trace_ok = Trace('data_ok', "OK")
trace_defect = Trace('data_defect', "defect")
# descriptions are "metadata", they describe when and what has been outputed
# we check that they do not differ for the two program runs
assert(trace_ok._descriptions == trace_defect._descriptions)
# we can then use one iterator to acces both data sets
it = Iterator(trace_ok._descriptions)
# we want to see matrix A both from the run we know was OK and that where was error
a_mat_ok = Snapshot(trace_ok, "a_mat", it)
a_mat_defect = Snapshot(trace_defect, "a_mat", it)
# we also want to see where they differ, so that we can find out where the difference originates
a_mat_diff = Difference(a_mat_ok, a_mat_defect)
# we have created 3 views, lets group them into a list
snapshot_set = [a_mat_ok, a_mat_defect, a_mat_diff]
# and tell the Plotter to show them. Note, that all the plots were created to follow
# the same iterator it, so we can change time point shown in all views by iterating it.
pl.reset(snapshot_set)
# Sample script showing a use case of ELPA matrix output for debugging
# In this case, we wanted to compare matrices for GPU and CPU variant of the code
# This feature is only experimental and will probably change
# The recomanded ussage is the following. Go to the directory of this script and run:
# ipython -i ../plot.py
# than run within python the command:
# run -i script.py
# Now a window with the plot should be created. Rearange your windows such that you can
# see both console and plot and iterate using the iterators, change views or create new, etc.
# If you want to modify this file and re-run it without closing the plotting window, comment
# out the two following lines. If you do not want to reload the data, comment out creating of
# traces.
# To try this example untar the file data.tgz
# create new matplotlib figure and pass it to the Plotter
fig = plt.figure()
pl = Plotter(fig)
# load two traces, one from a run with GPU enabled, one without
# note that this might take a lot of time, so if we have allready run this script and than only
# changed something in the following, we might choose to comment out the following commands
trace = Trace('data_gpu', "w gpu")
trace_nongpu = Trace('data_nongpu', "nogpu")
# descriptions are "metadata", they describe when and what has been outputed
# we check that they do not differ for the two program runs
assert(trace._descriptions == trace_nongpu._descriptions)
# we can then use one iterator to acces both data sets
it = Iterator(trace._descriptions)
# we want to see two matrices from the run with GPU, we have both matrix on host and on device
a_mat = Snapshot(trace, "a_mat", it)
a_dev = Snapshot(trace, "a_dev", it)
# we are also interested in difference between the two matrices
a_mat_dev_diff = Difference(a_mat, a_dev)
# from the second trace we can extract only matrix on host (no matrix on device)
a_nongpu = Snapshot(trace_nongpu, "a_mat", it)
# we have created 4 views, lets group them into a list
snapshot_set = [a_mat, a_dev, a_mat_dev_diff, a_nongpu]
# and tell the Plotter to show them. Note, that all the plots were created to follow
# the same iterator it, so we can change time point shown in all views by iterating it.
pl.reset(snapshot_set)
# we can also create another iterator it_2 and the same shnapshot set, but binded to this new
# iterator it_2, to be able to switch between two time instances
it_2 = Iterator(trace._descriptions)
a_mat_2 = Snapshot(trace, "a_mat", it_2)
a_dev_2 = Snapshot(trace, "a_dev", it_2)
a_mat_dev_diff_2 = Difference(a_mat_2, a_dev_2)
a_nongpu_2 = Snapshot(trace_nongpu, "a_mat", it_2)
# we can then show this new set by calling pl.reset(snapshot_set_2)
snapshot_set_2 = [a_mat_2, a_dev_2, a_mat_dev_diff_2, a_nongpu_2]
# we have allready used Difference of two different matrices at the same time instance. We can also
# define differences of the same matrix in different time instances and see what has changed
a_mat_diff = Difference(a_mat, a_mat_2)
a_dev_diff = Difference(a_dev, a_dev_2)
a_nongpu_diff = Difference(a_nongpu, a_nongpu_2)
# again we group them to a set and can show them by pl.reset(diffs_set)
diffs_set = [a_mat_diff, a_dev_diff, a_nongpu_diff, a_mat]
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment