<div dir="ltr"><div dir="ltr"><br></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Thu, Jun 23, 2022 at 3:02 PM Barry Smith <<a href="mailto:bsmith@petsc.dev" target="_blank">bsmith@petsc.dev</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div><div><br></div>  It looks like the current code copies the nonzero values to the CPU from the MPI matrix (with the calls PetscCall(MatSeqAIJGetArrayRead(mpimat->A,&aav));<br>  PetscCall(MatSeqAIJGetArrayRead(mpimat->B,&bav));, then copies them into the CPU memory of the Seq matrix. When the matrix entries are next accessed on the GPU it should automatically copy them down to the GPU.  So the code looks ok even for GPUs. We'll need to see the full error message with what the "invalid pointer" is.</div></blockquote><div><br></div><div>I showed Matt how to peek into offloadmask and he found that it is a host state, but this is not the issue. The access method should do the copy to the device.</div><div><br></div><div>I am thinking the logic here might be wrong. (Matt fixed "VEC" --> "MAT" in the comparison below).</div><div><br></div><div>Matt, is the issue that you are calling  <b>MatSeqAIJCUSPARSEGetArrayRead<font face="monospace"> </font></b>and getting a host pointer?</div><div><br></div>I think the state of amgx->localA after the call to MatSeqAIJCUSPARSEGetArrayRead should be "BOTH" because this copied the data to the device so they are both valid and you should have device data.</div><div class="gmail_quote"><font face="monospace"><br></font></div><div class="gmail_quote"><font face="monospace">211   PetscBool is_dev_ptrs;<br>212   PetscCall(PetscObjectTypeCompareAny((PetscObject)amgx->localA, &is_dev_ptrs, VECCUDA, VECMPICUDA, VECSEQCUDA, ""));<br>213<br>214   if (is_dev_ptrs) {<br><b>216     PetscCall(MatSeqAIJCUSPARSEGetArrayRead(amgx->localA, &amgx->values));<br></b>217   } else {<br>219     PetscCall(MatSeqAIJGetArrayRead(amgx->localA, &amgx->values)); <br>220   }</font><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div><div><br></div><div>  Barry</div><div><br><div><br></div><div> Yes this routine is terribly inefficient for GPU matrices, it needs to be specialized to not use the GPU memory but that is a separate issue from there being bugs in the current code.</div><div><br></div><div>  The code also seems to implicitly assume the parallel matrix has the same nonzero pattern with a reuse. This should be checked with each use by stashing the nonzero state of the matrix into the sequential matrix and making sure the parallel matrix has that same stashed value each time. Currently if one changes the nonzero matrix of the parallel matrix one is likely to get random confusing crashes due to memory corruption. But likely not the problem here.<br><div><br><blockquote type="cite"><div>On Jun 23, 2022, at 2:23 PM, Mark Adams <<a href="mailto:mfadams@lbl.gov" target="_blank">mfadams@lbl.gov</a>> wrote:</div><br><div><div dir="ltr"><div>We have a bug in the AMGx test snes_tests-ex13_amgx in parallel.</div><div>Matt Martineau found that MatMPIAIJGetLocalMat worked in the first pass in the code below, where the local matrix is created (INITIAL), but in the next pass, when "REUSE" is used, he sees an invalid pointer.</div><div>Matt found that it does have offloadmask == CPU. </div><div>Maybe it is missing logic to put the output in same state as the input?</div><div><br></div><div>Any ideas on this or should I just dig into it?</div><div><br></div><div>Thanks,</div><div><pre style="box-sizing:inherit;margin-top:4px;margin-bottom:4px;padding:8px;font-size:12px;line-height:1.50001;font-variant-ligatures:none;white-space:pre-wrap;word-break:normal;border-radius:4px;color:rgb(29,28,29);font-family:Monaco,Menlo,Consolas,"Courier New",monospace">bool partial_setup_allowed = (pc->setupcalled && pc->flag != DIFFERENT_NONZERO_PATTERN);
199   if (amgx->nranks > 1) {
200     if (partial_setup_allowed) {
202       PetscCall(MatMPIAIJGetLocalMat(Pmat, MAT_REUSE_MATRIX, &amgx->localA)); // This path seems doesn't work by the time we reach AmgX API
203     } else {
205       PetscCall(MatMPIAIJGetLocalMat(Pmat, MAT_INITIAL_MATRIX, &amgx->localA)); // This path works
206     }
207   } else {
208     amgx->localA = Pmat;
209   }
210</pre></div></div>
</div></blockquote></div><br></div></div></div></blockquote></div></div>