Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add MPIBlockDiag and MPILinearOperator #26

Merged
merged 21 commits into from
Jul 3, 2023
Merged

Conversation

rohanbabbar04
Copy link
Collaborator

@rohanbabbar04 rohanbabbar04 commented Jun 27, 2023

  • Added MPIBlockDiag with _matvec and _rmatvec which now uses DistributedArray
  • Added MPILinearOperator class
  • Added basic classes(_ScaledLinearOperator, _AdjointLinearOperator, etc) and made them input and output DistributedArray.
  • Added tests to verify above classes.
  • Upgrade scipy to 1.8 and python to 3.8
  • Updated docs for sphinx

Copy link
Contributor

@mrava87 mrava87 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rohanbabbar04, thanks for this PR. So far I struggle a bit to understand the rationale behind this operator. I had a few comments in the closed PR that I put here again, hopefully your answers (and example!) will help clarify my doubts.

  • [Taken from closed PR] Looking at your example, I am not sure I understand how you envision/designed MPIBlockDiag… my idea is that if you have a block diagonal operator with N operators (N being the number of ranks), each rank will build one pylops operator and pass it to the MPIBlockDiag, so that once matvec/rmatvec is called each rank will compute their portion… so if you were to compare your new implementation with an equivalent pylops one, the pylops operator will have to take all of those operators and give the same result…. For simplicity take this example: you have 3 ranks and 3 5x5 matrices which you wrap into 3 MatrixMult operators. The first is filled with 1s, the second with 2s, the third with 3s.. now for pylops-MPI each rank makes one MatrixMult operator and passes it to MPIBlockDiag… the x is also distributed and can be just full of 1s for simplicity. Unless I don’t understand your example it doesn’t seem like it is built like this, rather each rank seems to make all of the ops…
  • Based on the above, it seems like your x and y are not DistributedArray, instead just numpy arrays. Why? Again, I would think we should have distributed arrays passed to MPI operators, so that internally it is easy to get the portion needed
  • In the PR you closed you had created a LinearOperator class and subclassed MPIBlockDiag. Was there any reason/benefit from doing that, or right now you do not see any use wrt MPIBlockDiag?

pylops_mpi/basicoperators/__init__.py Outdated Show resolved Hide resolved
pylops_mpi/__init__.py Outdated Show resolved Hide resolved
pylops_mpi/basicoperators/BlockDiag.py Outdated Show resolved Hide resolved
pylops_mpi/basicoperators/BlockDiag.py Outdated Show resolved Hide resolved
pylops_mpi/basicoperators/BlockDiag.py Outdated Show resolved Hide resolved
pylops_mpi/basicoperators/BlockDiag.py Outdated Show resolved Hide resolved
pylops_mpi/basicoperators/BlockDiag.py Outdated Show resolved Hide resolved
@rohanbabbar04 rohanbabbar04 force-pushed the mpi_block_diag branch 2 times, most recently from 081bfd4 to 2809909 Compare June 29, 2023 06:57
Added * in pylops_mpi/__init__
Updated pylops_mpi/basicoperators/__init__.py
@rohanbabbar04
Copy link
Collaborator Author

@mrava87 Done the changes, if the code and tests are good to go, we can merge this
I will make a new PR for the example(Post Stack one)

Copy link
Contributor

@mrava87 mrava87 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good job! Still quite a few comments but I think we are getting closer to having a good MPIBlockDiag operator.

For now I think we can stick to this implementation. Later we can consider maybe adding also what you had originally, allowing users to choose (depending on the scenario) if they want to create&pass operators per rank or all of them from all ranks - the second may be more flexible for complex scenarios but I suspect the former will be the most used one as in most cases operators will be the same for all ranks, just filled with different 'content'. (or just doing the same think to different parts of the model and data vector)

pylops_mpi/basicoperators/BlockDiag.py Outdated Show resolved Hide resolved
pylops_mpi/basicoperators/BlockDiag.py Outdated Show resolved Hide resolved
pylops_mpi/basicoperators/BlockDiag.py Outdated Show resolved Hide resolved
pylops_mpi/basicoperators/BlockDiag.py Outdated Show resolved Hide resolved
pylops_mpi/basicoperators/BlockDiag.py Show resolved Hide resolved
pylops_mpi/basicoperators/BlockDiag.py Show resolved Hide resolved
pylops_mpi/basicoperators/BlockDiag.py Outdated Show resolved Hide resolved
pylops_mpi/basicoperators/BlockDiag.py Outdated Show resolved Hide resolved
tests/test_blockdiag.py Outdated Show resolved Hide resolved
tests/test_blockdiag.py Outdated Show resolved Hide resolved
@rohanbabbar04
Copy link
Collaborator Author

rohanbabbar04 commented Jul 1, 2023

Hi @mrava87,

  • I have added MPILinearOperator class and made MPIBlockDiag extend that.
  • Added important classes(_ScaledLinearOperator, _AdjointLinearOperator, etc) and made them input and output DistributedArray.
  • Since we are adding the above classes we need to test them. For the linearop tests(for Scaled, Prod and Sum) I have used MPIBlockDiag, as our linearop.

@rohanbabbar04 rohanbabbar04 changed the title Add MPIBlockDiag Add MPIBlockDiag and MPILinearOperator Jul 1, 2023
Copy link
Contributor

@mrava87 mrava87 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks great!

I made just a few comments on the LinearOperator. Most should be easy to handle, but there is one or two where I cannot understand some of your code choices that would be good to discuss/agree upon before moving ahead.

After that, for me this is ready to be merged :)

pylops_mpi/LinearOperator.py Outdated Show resolved Hide resolved
pylops_mpi/LinearOperator.py Outdated Show resolved Hide resolved
pylops_mpi/LinearOperator.py Outdated Show resolved Hide resolved

def matvec(self, x: DistributedArray) -> DistributedArray:
if self.Op:
y = DistributedArray(global_shape=self.base_comm.allreduce(self.shape[1]), dtype=x.dtype)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

self.base_comm.allreduce(self.shape[1]) why?

You ask the user to pass shape and from the doc you say Shape of the MPI Linear Operator. which makes me think is the global shape. Also in MPIBlockDiag the shape is computed as shape = (base_comm.allreduce(self.nops), base_comm.allreduce(self.mops)) which means it is the global shape.. so why this?


def rmatvec(self, x: DistributedArray) -> DistributedArray:
if self.Op:
y = DistributedArray(global_shape=self.base_comm.allreduce(self.shape[1]), dtype=x.dtype)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above

tests/test_linearop.py Show resolved Hide resolved
tests/test_linearop.py Show resolved Hide resolved
@rohanbabbar04
Copy link
Collaborator Author

rohanbabbar04 commented Jul 2, 2023

  • I have made MPILinearOperator class a standalone class(not extending pylops.LinearOperator), have add some docstrings comment for different methods as a reason.
  • Currently dot only supports matvec operations, not matmat.
  • Thinking about asmpilinearoperator, currently reverted from self.base_comm.allreduce(self.shape[1]) to self.shape[1], but will have to handled for different operators as a direct self.Op._matvec(x.local_array) will possibly give an error...
  • For the MPILinearOperator, there are mainly 3 parameters we primarily use which was in pylops.LinearOperator, which are Op, shape and dtype..

@mrava87
Copy link
Contributor

mrava87 commented Jul 2, 2023

Great, I think this is ready to go. We will see if things like matmat are needed in future but for now what we have in MPILinearOperator should be enough to be able to successfully solve our initial use-cases :)

@rohanbabbar04 rohanbabbar04 merged commit b70f89d into main Jul 3, 2023
@rohanbabbar04 rohanbabbar04 deleted the mpi_block_diag branch July 3, 2023 03:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants