992 std::ostringstream
os;
994 std::cerr <<
os.str ();
999 std::ostringstream
os;
1007 std::cerr <<
os.str ();
1020 size_t constantNumPackets = this->constantNumberOfPackets ();
1022 std::ostringstream os;
1023 os << *prefix <<
"constantNumPackets=" << constantNumPackets << endl;
1024 std::cerr << os.str ();
1032 if (constantNumPackets == 0) {
1034 std::ostringstream os;
1035 os << *prefix <<
"3. (Re)allocate num{Ex,Im}portPacketsPerLID"
1037 std::cerr << os.str ();
1041 this->reallocArraysForNumPacketsPerLid (exportLIDs.extent (0),
1042 remoteLIDs.extent (0));
1046 std::ostringstream os;
1047 os << *prefix <<
"4. packAndPrepare: before, "
1050 std::cerr << os.str ();
1053 doPackAndPrepare(src, exportLIDs, constantNumPackets);
1055 this->exports_.sync_host();
1058 this->exports_.sync_device();
1062 std::ostringstream os;
1063 os << *prefix <<
"5.1. After packAndPrepare, "
1066 std::cerr << os.str ();
1072 if (constantNumPackets != 0) {
1077 const size_t rbufLen = remoteLIDs.extent (0) * constantNumPackets;
1078 reallocImportsIfNeeded (rbufLen, verbose, prefix.get (), canTryAliasing, CM);
1082 bool needCommunication =
true;
1085 const this_type* srcDistObj =
dynamic_cast<const this_type*
> (&src);
1087 if (revOp == DoReverse && ! this->isDistributed ()) {
1088 needCommunication =
false;
1097 else if (revOp == DoForward && srcDistObj != NULL &&
1098 ! srcDistObj->isDistributed ()) {
1099 needCommunication =
false;
1102 if (! needCommunication) {
1104 std::ostringstream os;
1105 os << *prefix <<
"Comm not needed; skipping" << endl;
1106 std::cerr << os.str ();
1110 ProfilingRegion region_dpw
1111 (
"Tpetra::DistObject::doTransferNew::doPostsAndWaits");
1112#ifdef HAVE_TPETRA_TRANSFER_TIMERS
1115 Teuchos::TimeMonitor doPostsAndWaitsMon (*doPostsAndWaitsTimer_);
1119 std::ostringstream os;
1120 os << *prefix <<
"7.0. "
1121 << (revOp == DoReverse ?
"Reverse" :
"Forward")
1123 std::cerr << os.str ();
1126 doPosts(distributorPlan, constantNumPackets, commOnHost, prefix, canTryAliasing, CM);
1131 template <
class Packet,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1133 DistObject<Packet, LocalOrdinal, GlobalOrdinal, Node>::
1134 endTransfer(
const SrcDistObject& src,
1135 const ::Tpetra::Details::Transfer<local_ordinal_type, global_ordinal_type, node_type>& transfer,
1136 const char modeString[],
1137 const ReverseOption revOp,
1139 bool restrictedMode)
1141 using Details::Behavior;
1142 using ::Tpetra::Details::dualViewStatusToString;
1143 using ::Tpetra::Details::getArrayViewFromDualView;
1144 using Details::ProfilingRegion;
1145 using Kokkos::Compat::getArrayView;
1146 using Kokkos::Compat::getConstArrayView;
1147 using Kokkos::Compat::getKokkosViewDeepCopy;
1148 using Kokkos::Compat::create_const_view;
1151 using Details::ProfilingRegion;
1152 const char funcName[] =
"Tpetra::DistObject::doTransfer";
1154 ProfilingRegion region_doTransfer(funcName);
1155 const bool verbose = Behavior::verbose(
"DistObject");
1156 std::shared_ptr<std::string> prefix;
1158 std::ostringstream os;
1159 prefix = this->
createPrefix(
"DistObject",
"doTransfer");
1160 os << *prefix <<
"Source type: " << Teuchos::typeName(src)
1161 <<
", Target type: " << Teuchos::typeName(*
this) << endl;
1162 std::cerr << os.str();
1175 const bool debug = Behavior::debug(
"DistObject");
1177 if (! restrictedMode && revOp == DoForward) {
1178 const bool myMapSameAsTransferTgtMap =
1179 this->getMap ()->isSameAs (* (transfer.getTargetMap ()));
1180 TEUCHOS_TEST_FOR_EXCEPTION
1181 (! myMapSameAsTransferTgtMap, std::invalid_argument,
1182 "Tpetra::DistObject::" << modeString <<
": For forward-mode "
1183 "communication, the target DistObject's Map must be the same "
1184 "(in the sense of Tpetra::Map::isSameAs) as the input "
1185 "Export/Import object's target Map.");
1187 else if (! restrictedMode && revOp == DoReverse) {
1188 const bool myMapSameAsTransferSrcMap =
1189 this->getMap ()->isSameAs (* (transfer.getSourceMap ()));
1190 TEUCHOS_TEST_FOR_EXCEPTION
1191 (! myMapSameAsTransferSrcMap, std::invalid_argument,
1192 "Tpetra::DistObject::" << modeString <<
": For reverse-mode "
1193 "communication, the target DistObject's Map must be the same "
1194 "(in the sense of Tpetra::Map::isSameAs) as the input "
1195 "Export/Import object's source Map.");
1197 else if (restrictedMode && revOp == DoForward) {
1198 const bool myMapLocallyFittedTransferTgtMap =
1199 this->getMap ()->isLocallyFitted (* (transfer.getTargetMap ()));
1200 TEUCHOS_TEST_FOR_EXCEPTION
1201 (! myMapLocallyFittedTransferTgtMap , std::invalid_argument,
1202 "Tpetra::DistObject::" << modeString <<
": For forward-mode "
1203 "communication using restricted mode, Export/Import object's "
1204 "target Map must be locally fitted (in the sense of "
1205 "Tpetra::Map::isLocallyFitted) to target DistObject's Map.");
1208 const bool myMapLocallyFittedTransferSrcMap =
1209 this->getMap ()->isLocallyFitted (* (transfer.getSourceMap ()));
1210 TEUCHOS_TEST_FOR_EXCEPTION
1211 (! myMapLocallyFittedTransferSrcMap, std::invalid_argument,
1212 "Tpetra::DistObject::" << modeString <<
": For reverse-mode "
1213 "communication using restricted mode, Export/Import object's "
1214 "source Map must be locally fitted (in the sense of "
1215 "Tpetra::Map::isLocallyFitted) to target DistObject's Map.");
1221 const this_type* srcDistObj =
dynamic_cast<const this_type*
> (&src);
1222 if (srcDistObj !=
nullptr) {
1223 if (revOp == DoForward) {
1224 const bool srcMapSameAsImportSrcMap =
1225 srcDistObj->getMap ()->isSameAs (* (transfer.getSourceMap ()));
1226 TEUCHOS_TEST_FOR_EXCEPTION
1227 (! srcMapSameAsImportSrcMap, std::invalid_argument,
1228 "Tpetra::DistObject::" << modeString <<
": For forward-mode "
1229 "communication, the source DistObject's Map must be the same "
1230 "as the input Export/Import object's source Map.");
1233 const bool srcMapSameAsImportTgtMap =
1234 srcDistObj->getMap ()->isSameAs (* (transfer.getTargetMap ()));
1235 TEUCHOS_TEST_FOR_EXCEPTION
1236 (! srcMapSameAsImportTgtMap, std::invalid_argument,
1237 "Tpetra::DistObject::" << modeString <<
": For reverse-mode "
1238 "communication, the source DistObject's Map must be the same "
1239 "as the input Export/Import object's target Map.");
1244 Distributor& distor = transfer.getDistributor ();
1245 const Details::DistributorPlan& distributorPlan = (revOp == DoForward) ? distor.getPlan() : *distor.getPlan().getReversePlan();
1247 TEUCHOS_TEST_FOR_EXCEPTION
1248 (debug && restrictedMode &&
1249 (transfer.getPermuteToLIDs_dv().extent(0) != 0 ||
1250 transfer.getPermuteFromLIDs_dv().extent(0) != 0),
1251 std::invalid_argument,
1252 "Tpetra::DistObject::" << modeString <<
": Transfer object "
1253 "cannot have permutes in restricted mode.");
1256 const bool commOnHost = ! Behavior::assumeMpiIsCudaAware ();
1258 std::ostringstream os;
1259 os << *prefix <<
"doTransfer: Use new interface; "
1260 "commOnHost=" << (commOnHost ?
"true" :
"false") << endl;
1261 std::cerr << os.str ();
1264 using const_lo_dv_type =
1265 Kokkos::DualView<const local_ordinal_type*, buffer_device_type>;
1266 const_lo_dv_type permuteToLIDs = (revOp == DoForward) ?
1267 transfer.getPermuteToLIDs_dv () :
1268 transfer.getPermuteFromLIDs_dv ();
1269 const_lo_dv_type permuteFromLIDs = (revOp == DoForward) ?
1270 transfer.getPermuteFromLIDs_dv () :
1271 transfer.getPermuteToLIDs_dv ();
1272 const_lo_dv_type remoteLIDs = (revOp == DoForward) ?
1273 transfer.getRemoteLIDs_dv () :
1274 transfer.getExportLIDs_dv ();
1275 const_lo_dv_type exportLIDs = (revOp == DoForward) ?
1276 transfer.getExportLIDs_dv () :
1277 transfer.getRemoteLIDs_dv ();
1278 const bool canTryAliasing = (revOp == DoForward) ?
1279 transfer.areRemoteLIDsContiguous() :
1280 transfer.areExportLIDsContiguous();
1282 size_t constantNumPackets = this->constantNumberOfPackets ();
1286 if (constantNumPackets != 0) {
1291 const size_t rbufLen = remoteLIDs.extent (0) * constantNumPackets;
1292 reallocImportsIfNeeded (rbufLen, verbose, prefix.get (), canTryAliasing, CM);
1296 bool needCommunication =
true;
1299 const this_type* srcDistObj =
dynamic_cast<const this_type*
> (&src);
1301 if (revOp == DoReverse && ! this->isDistributed ()) {
1302 needCommunication =
false;
1311 else if (revOp == DoForward && srcDistObj != NULL &&
1312 ! srcDistObj->isDistributed ()) {
1313 needCommunication =
false;
1316 if (! needCommunication) {
1318 std::ostringstream os;
1319 os << *prefix <<
"Comm not needed; skipping" << endl;
1320 std::cerr << os.str ();
1324 distributorActor_.doWaits(distributorPlan);
1327 std::ostringstream os;
1328 os << *prefix <<
"8. unpackAndCombine" << endl;
1329 std::cerr << os.str ();
1331 doUnpackAndCombine(remoteLIDs, constantNumPackets, CM);
1336 std::ostringstream os;
1337 os << *prefix <<
"9. Done!" << endl;
1338 std::cerr << os.str ();
1342 std::ostringstream os;
1343 os << *prefix <<
"Tpetra::DistObject::doTransfer: Done!" << endl;
1344 std::cerr << os.str ();
1348 template <
class Packet,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1350 DistObject<Packet, LocalOrdinal, GlobalOrdinal, Node>::
1351 doPosts(
const Details::DistributorPlan& distributorPlan,
1352 size_t constantNumPackets,
1354 std::shared_ptr<std::string> prefix,
1355 const bool canTryAliasing,
1358 using ::Tpetra::Details::dualViewStatusToString;
1359 using ::Tpetra::Details::getArrayViewFromDualView;
1360 using Kokkos::Compat::create_const_view;
1365 if (constantNumPackets == 0) {
1367 std::ostringstream os;
1368 os << *prefix <<
"7.1. Variable # packets / LID: first comm "
1369 <<
"(commOnHost = " << (commOnHost ?
"true" :
"false") <<
")"
1371 std::cerr << os.str ();
1373 size_t totalImportPackets = 0;
1375 if (this->numExportPacketsPerLID_.need_sync_host ()) {
1376 this->numExportPacketsPerLID_.sync_host ();
1378 if (this->numImportPacketsPerLID_.need_sync_host ()) {
1379 this->numImportPacketsPerLID_.sync_host ();
1381 this->numImportPacketsPerLID_.modify_host ();
1383 create_const_view (this->numExportPacketsPerLID_.view_host ());
1384 auto numImp_h = this->numImportPacketsPerLID_.view_host ();
1388 std::ostringstream os;
1389 os << *prefix <<
"Call doPostsAndWaits"
1391 std::cerr << os.str ();
1393 distributorActor_.doPostsAndWaits(distributorPlan, numExp_h, 1, numImp_h);
1396 std::ostringstream os;
1397 os << *prefix <<
"Count totalImportPackets" << std::endl;
1398 std::cerr << os.str ();
1400 using the_dev_type =
typename decltype (numImp_h)::device_type;
1401 totalImportPackets = countTotalImportPackets<the_dev_type> (numImp_h);
1404 this->numExportPacketsPerLID_.sync_device ();
1405 this->numImportPacketsPerLID_.sync_device ();
1406 this->numImportPacketsPerLID_.modify_device ();
1407 auto numExp_d = create_const_view
1408 (this->numExportPacketsPerLID_.view_device ());
1409 auto numImp_d = this->numImportPacketsPerLID_.view_device ();
1413 std::ostringstream os;
1414 os << *prefix <<
"Call doPostsAndWaits"
1416 std::cerr << os.str ();
1418 distributorActor_.doPostsAndWaits(distributorPlan, numExp_d, 1, numImp_d);
1421 std::ostringstream os;
1422 os << *prefix <<
"Count totalImportPackets" << std::endl;
1423 std::cerr << os.str ();
1425 using the_dev_type =
typename decltype (numImp_d)::device_type;
1426 totalImportPackets = countTotalImportPackets<the_dev_type> (numImp_d);
1430 std::ostringstream os;
1431 os << *prefix <<
"totalImportPackets=" << totalImportPackets << endl;
1432 std::cerr << os.str ();
1434 this->reallocImportsIfNeeded (totalImportPackets, verbose,
1435 prefix.get (), canTryAliasing, CM);
1437 std::ostringstream os;
1438 os << *prefix <<
"7.3. Second comm" << std::endl;
1439 std::cerr << os.str ();
1445 this->numExportPacketsPerLID_.sync_host ();
1446 this->numImportPacketsPerLID_.sync_host ();
1455 auto numExportPacketsPerLID_av =
1457 auto numImportPacketsPerLID_av =
1465 this->imports_.clear_sync_state ();
1468 std::ostringstream os;
1469 os << *prefix <<
"Comm on "
1470 << (commOnHost ?
"host" :
"device")
1471 <<
"; call doPosts" << endl;
1472 std::cerr << os.str ();
1476 this->imports_.modify_host ();
1477 distributorActor_.doPosts
1479 create_const_view (this->exports_.view_host ()),
1480 numExportPacketsPerLID_av,
1481 this->imports_.view_host (),
1482 numImportPacketsPerLID_av);
1486 this->imports_.modify_device ();
1487 distributorActor_.doPosts
1489 create_const_view (this->exports_.view_device ()),
1490 numExportPacketsPerLID_av,
1491 this->imports_.view_device (),
1492 numImportPacketsPerLID_av);
1497 std::ostringstream os;
1498 os << *prefix <<
"7.1. Const # packets per LID: " << endl
1505 std::cerr << os.str ();
1512 this->imports_.clear_sync_state ();
1515 std::ostringstream os;
1516 os << *prefix <<
"7.2. Comm on "
1517 << (commOnHost ?
"host" :
"device")
1518 <<
"; call doPosts" << endl;
1519 std::cerr << os.str ();
1522 this->imports_.modify_host ();
1523 distributorActor_.doPosts
1525 create_const_view (this->exports_.view_host ()),
1527 this->imports_.view_host ());
1531 this->imports_.modify_device ();
1532 distributorActor_.doPosts
1534 create_const_view (this->exports_.view_device ()),
1536 this->imports_.view_device ());
1541 template <
class Packet,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1543 DistObject<Packet, LocalOrdinal, GlobalOrdinal, Node>::
1544 doPackAndPrepare(
const SrcDistObject& src,
1545 const Kokkos::DualView<const local_ordinal_type*, buffer_device_type>& exportLIDs,
1546 size_t& constantNumPackets)
1548 using Details::ProfilingRegion;
1552 ProfilingRegion region_pp
1553 (
"Tpetra::DistObject::doTransferNew::packAndPrepare");
1554#ifdef HAVE_TPETRA_TRANSFER_TIMERS
1557 Teuchos::TimeMonitor packAndPrepareMon (*packAndPrepareTimer_);
1577 std::ostringstream lclErrStrm;
1578 bool lclSuccess =
false;
1580 this->packAndPrepare (src, exportLIDs, this->exports_,
1581 this->numExportPacketsPerLID_,
1582 constantNumPackets);
1585 catch (std::exception& e) {
1586 lclErrStrm <<
"packAndPrepare threw an exception: "
1587 << endl << e.what();
1590 lclErrStrm <<
"packAndPrepare threw an exception "
1591 "not a subclass of std::exception.";
1593 const char gblErrMsgHeader[] =
"Tpetra::DistObject "
1594 "threw an exception in packAndPrepare on "
1595 "one or more processes in the DistObject's communicator.";
1596 auto comm = getMap()->getComm();
1597 Details::checkGlobalError(std::cerr, lclSuccess,
1598 lclErrStrm.str().c_str(),
1599 gblErrMsgHeader, *comm);
1602 this->packAndPrepare (src, exportLIDs, this->exports_,
1603 this->numExportPacketsPerLID_,
1604 constantNumPackets);
1608 template <
class Packet,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1610 DistObject<Packet, LocalOrdinal, GlobalOrdinal, Node>::
1611 doUnpackAndCombine(
const Kokkos::DualView<const local_ordinal_type*, buffer_device_type>& remoteLIDs,
1612 size_t constantNumPackets,
1615 using Details::ProfilingRegion;
1619 ProfilingRegion region_uc
1620 (
"Tpetra::DistObject::doTransferNew::unpackAndCombine");
1621#ifdef HAVE_TPETRA_TRANSFER_TIMERS
1624 Teuchos::TimeMonitor unpackAndCombineMon (*unpackAndCombineTimer_);
1628 std::ostringstream lclErrStrm;
1629 bool lclSuccess =
false;
1632 this->numImportPacketsPerLID_,
1633 constantNumPackets, CM);
1636 catch (std::exception& e) {
1637 lclErrStrm <<
"unpackAndCombine threw an exception: "
1638 << endl << e.what();
1641 lclErrStrm <<
"unpackAndCombine threw an exception "
1642 "not a subclass of std::exception.";
1644 const char gblErrMsgHeader[] =
"Tpetra::DistObject "
1645 "threw an exception in unpackAndCombine on "
1646 "one or more processes in the DistObject's communicator.";
1647 auto comm = getMap()->getComm();
1648 Details::checkGlobalError(std::cerr, lclSuccess,
1649 lclErrStrm.str().c_str(),
1650 gblErrMsgHeader, *comm);
1654 this->numImportPacketsPerLID_,
1655 constantNumPackets, CM);
1659 template <
class Packet,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1665 const Kokkos::DualView<
1668 const Kokkos::DualView<
1674 template <
class Packet,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1679 const Kokkos::DualView<
1691 template <
class Packet,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1695 (
const Kokkos::DualView<
1709 template <
class Packet,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1712 print (std::ostream&
os)
const
1714 using Teuchos::FancyOStream;
1715 using Teuchos::getFancyOStream;
1717 using Teuchos::rcpFromRef;
1721 this->describe (*
out, Teuchos::VERB_DEFAULT);
1724 template <
class Packet,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1725 std::unique_ptr<std::string>
1730 auto map = this->getMap();
1731 auto comm =
map.is_null() ? Teuchos::null :
map->getComm();
1736 template<
class DistObjectType>
1739 Teuchos::RCP<DistObjectType>&
input,
1740 const Teuchos::RCP<
const Map<
1741 typename DistObjectType::local_ordinal_type,
1742 typename DistObjectType::global_ordinal_type,
1743 typename DistObjectType::node_type>>&
newMap)
1747 input = Teuchos::null;
1751 template<
class DistObjectType>
1755 auto newMap =
input->getMap ()->removeEmptyProcesses ();
1760#define TPETRA_DISTOBJECT_INSTANT(SCALAR, LO, GO, NODE) \
1761 template class DistObject< SCALAR , LO , GO , NODE >;
1765#define TPETRA_DISTOBJECT_INSTANT_CHAR(LO, GO, NODE) \
1766 template class DistObject< char , LO , GO , NODE >;