Skip to content

Commit

Permalink
Fully automatic grid size. (#100)
Browse files Browse the repository at this point in the history
This is nothing fancy, but just in the case where you don't even want to specify the number of slices, we have a fallback grid.
  • Loading branch information
william-dawson authored Feb 1, 2019
1 parent a20e118 commit 8a6f870
Show file tree
Hide file tree
Showing 7 changed files with 183 additions and 32 deletions.
13 changes: 8 additions & 5 deletions Source/C/ProcessGrid_c.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@ void ConstructGlobalProcessGrid_wrp(const int *world_comm,
const int *process_columns,
const int *process_slices,
const bool *be_verbose);
void ConstructGlobalProcessGridabr_wrp(const int *world_comm,
const int *process_slices,
const bool *be_verbose);
void ConstructGlobalProcessGrid_onlyslice_wrp(const int *world_comm,
const int *process_slices,
const bool *be_verbose);
void ConstructGlobalProcessGrid_default_wrp(const int *world_comm,
const bool *be_verbose);
void CopyProcessGrid_wrp(const int *ih_old_grid, int *ih_new_grid);
int GetGlobalMySlice_wrp();
int GetGlobalMyColumn_wrp();
Expand All @@ -22,8 +24,9 @@ void ConstructProcessGrid_wrp(int *ih_grid, const int *world_comm,
const int *process_rows,
const int *process_columns,
const int *process_slices);
void ConstructProcessGridabr_wrp(int *ih_grid, const int *world_comm,
const int *process_slices);
void ConstructProcessGrid_onlyslice_wrp(int *ih_grid, const int *world_comm,
const int *process_slices);
void ConstructProcessGrid_default_wrp(int *ih_grid, const int *world_comm);
int GetMySlice_wrp(const int *ih_grid);
int GetMyColumn_wrp(const int *ih_grid);
int GetMyRow_wrp(const int *ih_grid);
Expand Down
34 changes: 30 additions & 4 deletions Source/CPlusPlus/ProcessGrid.cc
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,25 @@ ProcessGrid::ProcessGrid(int process_rows, int process_columns,
////////////////////////////////////////////////////////////////////////////////
ProcessGrid::ProcessGrid(MPI_Comm world_comm, int process_slices) {
MPI_Fint temp_comm = MPI_Comm_c2f(world_comm);
ConstructProcessGridabr_wrp(ih_this, &temp_comm, &process_slices);
ConstructProcessGrid_onlyslice_wrp(ih_this, &temp_comm, &process_slices);
}

////////////////////////////////////////////////////////////////////////////////
ProcessGrid::ProcessGrid(MPI_Comm world_comm) {
MPI_Fint temp_comm = MPI_Comm_c2f(world_comm);
ConstructProcessGrid_default_wrp(ih_this, &temp_comm);
}

////////////////////////////////////////////////////////////////////////////////
ProcessGrid::ProcessGrid(int process_slices) {
MPI_Fint temp_comm = MPI_Comm_c2f(MPI_COMM_WORLD);
ConstructProcessGridabr_wrp(ih_this, &temp_comm, &process_slices);
ConstructProcessGrid_onlyslice_wrp(ih_this, &temp_comm, &process_slices);
}

////////////////////////////////////////////////////////////////////////////////
ProcessGrid::ProcessGrid() {
MPI_Fint temp_comm = MPI_Comm_c2f(MPI_COMM_WORLD);
ConstructProcessGrid_default_wrp(ih_this, &temp_comm);
}

//////////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -83,13 +95,27 @@ void ConstructGlobalProcessGrid(int process_rows, int process_columns,
void ConstructGlobalProcessGrid(MPI_Comm world_comm, int process_slices,
bool be_verbose) {
MPI_Fint temp_comm = MPI_Comm_c2f(world_comm);
ConstructGlobalProcessGridabr_wrp(&temp_comm, &process_slices, &be_verbose);
ConstructGlobalProcessGrid_onlyslice_wrp(&temp_comm, &process_slices,
&be_verbose);
}

////////////////////////////////////////////////////////////////////////////////
void ConstructGlobalProcessGrid(MPI_Comm world_comm, bool be_verbose) {
MPI_Fint temp_comm = MPI_Comm_c2f(world_comm);
ConstructGlobalProcessGrid_default_wrp(&temp_comm, &be_verbose);
}

////////////////////////////////////////////////////////////////////////////////
void ConstructGlobalProcessGrid(int process_slices, bool be_verbose) {
MPI_Fint temp_comm = MPI_Comm_c2f(MPI_COMM_WORLD);
ConstructGlobalProcessGridabr_wrp(&temp_comm, &process_slices, &be_verbose);
ConstructGlobalProcessGrid_onlyslice_wrp(&temp_comm, &process_slices,
&be_verbose);
}

////////////////////////////////////////////////////////////////////////////////
void ConstructGlobalProcessGrid(bool be_verbose) {
MPI_Fint temp_comm = MPI_Comm_c2f(MPI_COMM_WORLD);
ConstructGlobalProcessGrid_default_wrp(&temp_comm, &be_verbose);
}

////////////////////////////////////////////////////////////////////////////////
Expand Down
16 changes: 15 additions & 1 deletion Source/CPlusPlus/ProcessGrid.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,17 @@ class ProcessGrid {
//! Construct the process grid.
//! \param[in] world_comm a communicator that every process in the grid is
//! a part of.
//! \param[in] process_rows number of grid rows.
//! \param[in] process_slices number of grid slices.
ProcessGrid(MPI_Comm world_comm, int process_slices);
//! Construct the process grid.
//! \param[in] world_comm a communicator that every process in the grid is
//! a part of.
ProcessGrid(MPI_Comm world_comm);
//! Construct the process grid from comm world
//! \param[in] process_slices number of grid slices.
ProcessGrid(int process_slices);
//! Construct the process grid with no parameters.
ProcessGrid();
//! Copy constructor.
//!\param old_grid to copy from.
ProcessGrid(const ProcessGrid &old_grid);
Expand Down Expand Up @@ -83,10 +89,18 @@ void ConstructGlobalProcessGrid(int process_rows, int process_columns,
//! \param[in] be_verbose verbosity flag.
void ConstructGlobalProcessGrid(MPI_Comm world_comm, int process_slices,
bool be_verbose = false);
//! Construct the global process grid.
//! \param[in] world_comm a communicator that every process in the grid is
//! a part of.
//! \param[in] be_verbose verbosity flag.
void ConstructGlobalProcessGrid(MPI_Comm world_comm, bool be_verbose = false);
//! Construct the global process grid from comm world
//! \param[in] process_slices number of grid slices.
//! \param[in] be_verbose verbosity flag.
void ConstructGlobalProcessGrid(int process_slices, bool be_verbose = false);
//! Construct the global process grid from comm world
//! \param[in] be_verbose verbosity flag.
void ConstructGlobalProcessGrid(bool be_verbose = false);
//! Get the slice of the current process.
int GetGlobalMySlice();
//! Get the column of the current process.
Expand Down
46 changes: 42 additions & 4 deletions Source/Fortran/ProcessGridModule.F90
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ SUBROUTINE ConstructProcessGrid_onlyslice(world_comm_, process_slices_in, &
IF (PRESENT(process_slices_in)) THEN
process_slices = process_slices_in
ELSE
process_slices = 1
CALL ComputeNumSlices(total_processors, process_slices)
END IF

!! Create a 3D grid
Expand Down Expand Up @@ -296,21 +296,30 @@ END SUBROUTINE ConstructNewProcessGrid_full
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!> Setup a process grid specifying only the slices
SUBROUTINE ConstructNewProcessGrid_onlyslice(grid, world_comm_, &
& process_slices)
& process_slices_in)
!> The grid to construct
TYPE(ProcessGrid_t), INTENT(INOUT) :: grid
!> A communicator that every process in the grid is a part of.
INTEGER(kind=c_int), INTENT(IN) :: world_comm_
!> The number of grid slices.
INTEGER(kind=c_int), INTENT(IN) :: process_slices
INTEGER(kind=c_int), INTENT(IN), OPTIONAL :: process_slices_in
!! Local Data
INTEGER :: process_rows, process_columns
LOGICAL :: be_verbose
INTEGER :: process_rows, process_columns, process_slices
INTEGER :: total_processors
INTEGER :: ierr

!! Total processors
CALL MPI_COMM_SIZE(world_comm_, total_processors, ierr)

!! Process Optional Parameters
IF (PRESENT(process_slices_in)) THEN
process_slices = process_slices_in
ELSE
CALL ComputeNumSlices(total_processors, process_slices)
END IF
WRITE(*,*) "COMPUTED NUMBER OF SLICES", process_slices

!! Create a 3D grid
CALL ComputeGridSize(total_processors, process_slices, process_rows, &
& process_columns)
Expand Down Expand Up @@ -621,5 +630,34 @@ SUBROUTINE ComputeGridSize(total_processors, set_slices, rows, columns)
END DO

END SUBROUTINE ComputeGridSize
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!> Pick an appropriate number of process slices for this calculation.
!> This routine will focus on whether we can make a square slice grid,
!> which gives pretty ideal performance.
SUBROUTINE ComputeNumSlices(total_processors, slices)
!> Total processors in the grid.
INTEGER, INTENT(IN) :: total_processors
!> Number of slices to use.
INTEGER, INTENT(OUT) :: slices
!! Local Variables
INTEGER :: slice_size
INTEGER :: slice_dim
LOGICAL :: found

!! Try manually values [4, 3, 2]. If they don't work, give up and use 1.
found = .FALSE.
DO slices = MIN(4, total_processors), 2, -1
slice_size = total_processors / slices
IF (slice_size * slices .NE. total_processors) CYCLE

slice_dim = FLOOR(SQRT(REAL(slice_size)))
IF (slice_dim*slice_dim .EQ. slice_size) THEN
FOUND = .TRUE.
EXIT
END IF
END DO
IF (.NOT. FOUND) slices = 1

END SUBROUTINE ComputeNumSlices
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
END MODULE ProcessGridModule
45 changes: 35 additions & 10 deletions Source/Wrapper/ProcessGridModule_wrp.F90
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ MODULE ProcessGridModule_wrp
END TYPE ProcessGrid_wrp
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
PUBLIC :: ConstructGlobalProcessGrid_wrp
PUBLIC :: ConstructGlobalProcessGridabr_wrp
PUBLIC :: ConstructGlobalProcessGrid_onlyslice_wrp
PUBLIC :: ConstructGlobalProcessGrid_default_wrp
PUBLIC :: GetGlobalMySlice_wrp
PUBLIC :: GetGlobalMyColumn_wrp
PUBLIC :: GetGlobalMyRow_wrp
Expand All @@ -25,7 +26,8 @@ MODULE ProcessGridModule_wrp
PUBLIC :: DestructGlobalProcessGrid_wrp
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
PUBLIC :: ConstructProcessGrid_wrp
PUBLIC :: ConstructProcessGridabr_wrp
PUBLIC :: ConstructProcessGrid_onlyslice_wrp
PUBLIC :: ConstructProcessGrid_default_wrp
PUBLIC :: CopyProcessGrid_wrp
PUBLIC :: GetMySlice_wrp
PUBLIC :: GetMyColumn_wrp
Expand All @@ -49,13 +51,23 @@ SUBROUTINE ConstructGlobalProcessGrid_wrp(world_comm_, process_rows_, &
END SUBROUTINE ConstructGlobalProcessGrid_wrp
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!> Wrap the process grid construction routine.
SUBROUTINE ConstructGlobalProcessGridabr_wrp(world_comm_, process_slices_, &
& be_verbose) bind(c,name="ConstructGlobalProcessGridabr_wrp")
SUBROUTINE ConstructGlobalProcessGrid_onlyslice_wrp(world_comm_, &
& process_slices_, be_verbose) &
& bind(c,name="ConstructGlobalProcessGrid_onlyslice_wrp")
INTEGER(kind=c_int), INTENT(IN) :: world_comm_
INTEGER(kind=c_int), INTENT(IN) :: process_slices_
LOGICAL(kind=c_bool), INTENT(IN) :: be_verbose
CALL ConstructProcessGrid(world_comm_, process_slices_, be_verbose)
END SUBROUTINE ConstructGlobalProcessGridabr_wrp
CALL ConstructProcessGrid(world_comm_, process_slices_in=process_slices_, &
& be_verbose_in=be_verbose)
END SUBROUTINE ConstructGlobalProcessGrid_onlyslice_wrp
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!> Wrap the process grid construction routine.
SUBROUTINE ConstructGlobalProcessGrid_default_wrp(world_comm_, be_verbose) &
& bind(c,name="ConstructGlobalProcessGrid_default_wrp")
INTEGER(kind=c_int), INTENT(IN) :: world_comm_
LOGICAL(kind=c_bool), INTENT(IN) :: be_verbose
CALL ConstructProcessGrid(world_comm_, be_verbose_in=be_verbose)
END SUBROUTINE ConstructGlobalProcessGrid_default_wrp
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!> Get the slice of the current process.
FUNCTION GetGlobalMySlice_wrp() RESULT(return_val) &
Expand Down Expand Up @@ -127,17 +139,30 @@ SUBROUTINE ConstructProcessGrid_wrp(ih_grid, world_comm_, process_rows_, &
END SUBROUTINE ConstructProcessGrid_wrp
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!> Construct a process grid.
SUBROUTINE ConstructProcessGridabr_wrp(ih_grid, world_comm_, process_slices_) &
& bind(c,name="ConstructProcessGridabr_wrp")
SUBROUTINE ConstructProcessGrid_onlyslice_wrp(ih_grid, world_comm_, &
& process_slices_) bind(c,name="ConstructProcessGrid_onlyslice_wrp")
INTEGER(kind=c_int), INTENT(INOUT) :: ih_grid(SIZE_wrp)
INTEGER(kind=c_int), INTENT(IN) :: world_comm_
INTEGER(kind=c_int), INTENT(IN) :: process_slices_
TYPE(ProcessGrid_wrp) :: h_grid

ALLOCATE(h_grid%data)
CALL ConstructNewProcessGrid(h_grid%data, world_comm_, process_slices_)
CALL ConstructNewProcessGrid(h_grid%data, world_comm_, &
& process_slices_in=process_slices_)
ih_grid = TRANSFER(h_grid,ih_grid)
END SUBROUTINE ConstructProcessGrid_onlyslice_wrp
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!> Construct a process grid.
SUBROUTINE ConstructProcessGrid_default_wrp(ih_grid, world_comm_) &
& bind(c,name="ConstructProcessGrid_default_wrp")
INTEGER(kind=c_int), INTENT(INOUT) :: ih_grid(SIZE_wrp)
INTEGER(kind=c_int), INTENT(IN) :: world_comm_
TYPE(ProcessGrid_wrp) :: h_grid

ALLOCATE(h_grid%data)
CALL ConstructNewProcessGrid(h_grid%data, world_comm_)
ih_grid = TRANSFER(h_grid,ih_grid)
END SUBROUTINE ConstructProcessGridabr_wrp
END SUBROUTINE ConstructProcessGrid_default_wrp
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!> Copy a process grid.
SUBROUTINE CopyProcessGrid_wrp(ih_old_grid, ih_new_grid) &
Expand Down
28 changes: 20 additions & 8 deletions UnitTests/test_psmatrix.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,18 @@ def test_grid(self):
self.assertEqual(total_procs, new_total_procs)
del new_grid

def test_grid_none(self):
'''
Test the most simplified process interface
'''
total_procs = self.process_rows * self.process_columns * \
self.process_slices
new_grid = nt.ProcessGrid()
new_total_procs = new_grid.GetNumRows() * new_grid.GetNumColumns() * \
new_grid.GetNumSlices()
self.assertEqual(total_procs, new_total_procs)
del new_grid

def test_read(self):
'''Test our ability to read and write matrices.'''
for param in self.parameters:
Expand Down Expand Up @@ -305,8 +317,8 @@ def test_slice(self):
space_mat = zeros((new_dim, new_dim))
if self.complex:
space_mat = 1j * space_mat
space_mat[:end_row - start_row + 1, :end_col -
start_col + 1] = sub_mat.todense()
space_mat[:end_row - start_row + 1, :end_col
- start_col + 1] = sub_mat.todense()
self.CheckMat = csr_matrix(space_mat)

# Compute with ntpoly
Expand Down Expand Up @@ -342,8 +354,8 @@ def test_grow(self):
matrix1[:small_size, :small_size], self.input_file1)

self.CheckMat = matrix1
self.CheckMat[:,small_size:] = 0
self.CheckMat[small_size:,:] = 0
self.CheckMat[:, small_size:] = 0
self.CheckMat[small_size:, :] = 0
ntmatrix1 = nt.Matrix_ps(self.input_file1, False)
ntmatrix1.Resize(param.rows)
ntmatrix1.WriteToMatrixMarket(self.result_file)
Expand Down Expand Up @@ -381,8 +393,8 @@ def __call__(self):
self.CheckMat = matrix1
for i in range(0, param.rows):
for j in range(0, param.columns):
if self.CheckMat[i,j] > 0.5:
self.CheckMat[i,j] = 0
if self.CheckMat[i, j] > 0.5:
self.CheckMat[i, j] = 0

ntmatrix1 = nt.Matrix_ps(self.input_file1, False)
ntmatrix2 = nt.Matrix_ps(ntmatrix1.GetActualDimension())
Expand Down Expand Up @@ -415,8 +427,8 @@ def __call__(self):
self.CheckMat = matrix1
for i in range(0, param.rows):
for j in range(0, param.columns):
if abs(self.CheckMat[i,j]) > 0.5:
self.CheckMat[i,j] = 0
if abs(self.CheckMat[i, j]) > 0.5:
self.CheckMat[i, j] = 0

ntmatrix1 = nt.Matrix_ps(self.input_file1, False)
ntmatrix2 = nt.Matrix_ps(ntmatrix1.GetActualDimension())
Expand Down
33 changes: 33 additions & 0 deletions UnitTests/test_psmatrixalgebra.py
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,39 @@ def test_multiply(self):

self.check_result()

def test_multiply_grid(self):
'''
Test routines to multiply two matrices with a default process grid.
'''
nt.DestructGlobalProcessGrid()
nt.ConstructGlobalProcessGrid()
for param in self.parameters:
matrix1 = param.create_matrix(snum=1, complex=self.complex1)
matrix2 = param.create_matrix(snum=2, complex=self.complex2)
self.write_matrix(matrix1, self.input_file1)
self.write_matrix(matrix2, self.input_file2)

self.CheckMat = matrix1.dot(matrix2)
comm.barrier()

if param.sparsity > 0.0:
ntmatrix1 = nt.Matrix_ps(self.input_file1, False)
else:
ntmatrix1 = nt.Matrix_ps(param.rows)
if param.sparsity2 > 0.0:
ntmatrix2 = nt.Matrix_ps(self.input_file2, False)
else:
ntmatrix2 = nt.Matrix_ps(param.rows)
ntmatrix3 = nt.Matrix_ps(param.rows)
memory_pool = nt.PMatrixMemoryPool(ntmatrix1)
ntmatrix3.Gemm(ntmatrix1, ntmatrix2, memory_pool)
ntmatrix3.WriteToMatrixMarket(self.result_file)
comm.barrier()

self.check_result()
nt.DestructGlobalProcessGrid()
nt.ConstructGlobalProcessGrid(rows, columns, slices)

def test_reverse(self):
'''Test routines to permute a matrix.'''
for param in self.parameters:
Expand Down

0 comments on commit 8a6f870

Please sign in to comment.