999 std::ostringstream
os;
1001 std::cerr <<
os.str ();
1006 std::ostringstream
os;
1014 std::cerr <<
os.str ();
1027 size_t constantNumPackets = this->constantNumberOfPackets ();
1029 std::ostringstream os;
1030 os << *prefix <<
"constantNumPackets=" << constantNumPackets << endl;
1031 std::cerr << os.str ();
1039 if (constantNumPackets == 0) {
1041 std::ostringstream os;
1042 os << *prefix <<
"3. (Re)allocate num{Ex,Im}portPacketsPerLID"
1044 std::cerr << os.str ();
1048 this->reallocArraysForNumPacketsPerLid (exportLIDs.extent (0),
1049 remoteLIDs.extent (0));
1053 std::ostringstream os;
1054 os << *prefix <<
"4. packAndPrepare: before, "
1057 std::cerr << os.str ();
1060 doPackAndPrepare(src, exportLIDs, constantNumPackets);
1062 this->exports_.sync_host();
1065 this->exports_.sync_device();
1069 std::ostringstream os;
1070 os << *prefix <<
"5.1. After packAndPrepare, "
1073 std::cerr << os.str ();
1079 if (constantNumPackets != 0) {
1084 const size_t rbufLen = remoteLIDs.extent (0) * constantNumPackets;
1085 reallocImportsIfNeeded (rbufLen, verbose, prefix.get (), canTryAliasing, CM);
1089 bool needCommunication =
true;
1092 const this_type* srcDistObj =
dynamic_cast<const this_type*
> (&src);
1094 if (revOp == DoReverse && ! this->isDistributed ()) {
1095 needCommunication =
false;
1104 else if (revOp == DoForward && srcDistObj != NULL &&
1105 ! srcDistObj->isDistributed ()) {
1106 needCommunication =
false;
1109 if (! needCommunication) {
1111 std::ostringstream os;
1112 os << *prefix <<
"Comm not needed; skipping" << endl;
1113 std::cerr << os.str ();
1117 ProfilingRegion region_dpw
1118 (
"Tpetra::DistObject::doTransferNew::doPostsAndWaits");
1119#ifdef HAVE_TPETRA_TRANSFER_TIMERS
1122 Teuchos::TimeMonitor doPostsAndWaitsMon (*doPostsAndWaitsTimer_);
1126 std::ostringstream os;
1127 os << *prefix <<
"7.0. "
1128 << (revOp == DoReverse ?
"Reverse" :
"Forward")
1130 std::cerr << os.str ();
1133 doPosts(distributorPlan, constantNumPackets, commOnHost, prefix, canTryAliasing, CM);
1138 template <
class Packet,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1140 DistObject<Packet, LocalOrdinal, GlobalOrdinal, Node>::
1141 endTransfer(
const SrcDistObject& src,
1142 const ::Tpetra::Details::Transfer<local_ordinal_type, global_ordinal_type, node_type>& transfer,
1143 const char modeString[],
1144 const ReverseOption revOp,
1146 bool restrictedMode)
1148 using Details::Behavior;
1149 using ::Tpetra::Details::dualViewStatusToString;
1150 using ::Tpetra::Details::getArrayViewFromDualView;
1151 using Details::ProfilingRegion;
1152 using Kokkos::Compat::getArrayView;
1153 using Kokkos::Compat::getConstArrayView;
1154 using Kokkos::Compat::getKokkosViewDeepCopy;
1155 using Kokkos::Compat::create_const_view;
1158 using Details::ProfilingRegion;
1159 const char funcName[] =
"Tpetra::DistObject::doTransfer";
1161 ProfilingRegion region_doTransfer(funcName);
1162 const bool verbose = Behavior::verbose(
"DistObject");
1163 std::shared_ptr<std::string> prefix;
1165 std::ostringstream os;
1166 prefix = this->
createPrefix(
"DistObject",
"doTransfer");
1167 os << *prefix <<
"Source type: " << Teuchos::typeName(src)
1168 <<
", Target type: " << Teuchos::typeName(*
this) << endl;
1169 std::cerr << os.str();
1182 const bool debug = Behavior::debug(
"DistObject");
1184 if (! restrictedMode && revOp == DoForward) {
1185 const bool myMapSameAsTransferTgtMap =
1186 this->getMap ()->isSameAs (* (transfer.getTargetMap ()));
1187 TEUCHOS_TEST_FOR_EXCEPTION
1188 (! myMapSameAsTransferTgtMap, std::invalid_argument,
1189 "Tpetra::DistObject::" << modeString <<
": For forward-mode "
1190 "communication, the target DistObject's Map must be the same "
1191 "(in the sense of Tpetra::Map::isSameAs) as the input "
1192 "Export/Import object's target Map.");
1194 else if (! restrictedMode && revOp == DoReverse) {
1195 const bool myMapSameAsTransferSrcMap =
1196 this->getMap ()->isSameAs (* (transfer.getSourceMap ()));
1197 TEUCHOS_TEST_FOR_EXCEPTION
1198 (! myMapSameAsTransferSrcMap, std::invalid_argument,
1199 "Tpetra::DistObject::" << modeString <<
": For reverse-mode "
1200 "communication, the target DistObject's Map must be the same "
1201 "(in the sense of Tpetra::Map::isSameAs) as the input "
1202 "Export/Import object's source Map.");
1204 else if (restrictedMode && revOp == DoForward) {
1205 const bool myMapLocallyFittedTransferTgtMap =
1206 this->getMap ()->isLocallyFitted (* (transfer.getTargetMap ()));
1207 TEUCHOS_TEST_FOR_EXCEPTION
1208 (! myMapLocallyFittedTransferTgtMap , std::invalid_argument,
1209 "Tpetra::DistObject::" << modeString <<
": For forward-mode "
1210 "communication using restricted mode, Export/Import object's "
1211 "target Map must be locally fitted (in the sense of "
1212 "Tpetra::Map::isLocallyFitted) to target DistObject's Map.");
1215 const bool myMapLocallyFittedTransferSrcMap =
1216 this->getMap ()->isLocallyFitted (* (transfer.getSourceMap ()));
1217 TEUCHOS_TEST_FOR_EXCEPTION
1218 (! myMapLocallyFittedTransferSrcMap, std::invalid_argument,
1219 "Tpetra::DistObject::" << modeString <<
": For reverse-mode "
1220 "communication using restricted mode, Export/Import object's "
1221 "source Map must be locally fitted (in the sense of "
1222 "Tpetra::Map::isLocallyFitted) to target DistObject's Map.");
1228 const this_type* srcDistObj =
dynamic_cast<const this_type*
> (&src);
1229 if (srcDistObj !=
nullptr) {
1230 if (revOp == DoForward) {
1231 const bool srcMapSameAsImportSrcMap =
1232 srcDistObj->getMap ()->isSameAs (* (transfer.getSourceMap ()));
1233 TEUCHOS_TEST_FOR_EXCEPTION
1234 (! srcMapSameAsImportSrcMap, std::invalid_argument,
1235 "Tpetra::DistObject::" << modeString <<
": For forward-mode "
1236 "communication, the source DistObject's Map must be the same "
1237 "as the input Export/Import object's source Map.");
1240 const bool srcMapSameAsImportTgtMap =
1241 srcDistObj->getMap ()->isSameAs (* (transfer.getTargetMap ()));
1242 TEUCHOS_TEST_FOR_EXCEPTION
1243 (! srcMapSameAsImportTgtMap, std::invalid_argument,
1244 "Tpetra::DistObject::" << modeString <<
": For reverse-mode "
1245 "communication, the source DistObject's Map must be the same "
1246 "as the input Export/Import object's target Map.");
1251 Distributor& distor = transfer.getDistributor ();
1252 const Details::DistributorPlan& distributorPlan = (revOp == DoForward) ? distor.getPlan() : *distor.getPlan().getReversePlan();
1254 TEUCHOS_TEST_FOR_EXCEPTION
1255 (debug && restrictedMode &&
1256 (transfer.getPermuteToLIDs_dv().extent(0) != 0 ||
1257 transfer.getPermuteFromLIDs_dv().extent(0) != 0),
1258 std::invalid_argument,
1259 "Tpetra::DistObject::" << modeString <<
": Transfer object "
1260 "cannot have permutes in restricted mode.");
1263 const bool commOnHost = ! Behavior::assumeMpiIsGPUAware ();
1265 std::ostringstream os;
1266 os << *prefix <<
"doTransfer: Use new interface; "
1267 "commOnHost=" << (commOnHost ?
"true" :
"false") << endl;
1268 std::cerr << os.str ();
1271 using const_lo_dv_type =
1272 Kokkos::DualView<const local_ordinal_type*, buffer_device_type>;
1273 const_lo_dv_type permuteToLIDs = (revOp == DoForward) ?
1274 transfer.getPermuteToLIDs_dv () :
1275 transfer.getPermuteFromLIDs_dv ();
1276 const_lo_dv_type permuteFromLIDs = (revOp == DoForward) ?
1277 transfer.getPermuteFromLIDs_dv () :
1278 transfer.getPermuteToLIDs_dv ();
1279 const_lo_dv_type remoteLIDs = (revOp == DoForward) ?
1280 transfer.getRemoteLIDs_dv () :
1281 transfer.getExportLIDs_dv ();
1282 const_lo_dv_type exportLIDs = (revOp == DoForward) ?
1283 transfer.getExportLIDs_dv () :
1284 transfer.getRemoteLIDs_dv ();
1285 const bool canTryAliasing = (revOp == DoForward) ?
1286 transfer.areRemoteLIDsContiguous() :
1287 transfer.areExportLIDsContiguous();
1289 size_t constantNumPackets = this->constantNumberOfPackets ();
1293 if (constantNumPackets != 0) {
1298 const size_t rbufLen = remoteLIDs.extent (0) * constantNumPackets;
1299 reallocImportsIfNeeded (rbufLen, verbose, prefix.get (), canTryAliasing, CM);
1303 bool needCommunication =
true;
1306 const this_type* srcDistObj =
dynamic_cast<const this_type*
> (&src);
1308 if (revOp == DoReverse && ! this->isDistributed ()) {
1309 needCommunication =
false;
1318 else if (revOp == DoForward && srcDistObj != NULL &&
1319 ! srcDistObj->isDistributed ()) {
1320 needCommunication =
false;
1323 if (! needCommunication) {
1325 std::ostringstream os;
1326 os << *prefix <<
"Comm not needed; skipping" << endl;
1327 std::cerr << os.str ();
1331 distributorActor_.doWaits(distributorPlan);
1334 std::ostringstream os;
1335 os << *prefix <<
"8. unpackAndCombine - remoteLIDs " << remoteLIDs.extent(0) <<
", constantNumPackets " << constantNumPackets << endl;
1336 std::cerr << os.str ();
1338 doUnpackAndCombine(remoteLIDs, constantNumPackets, CM);
1343 std::ostringstream os;
1344 os << *prefix <<
"9. Done!" << endl;
1345 std::cerr << os.str ();
1349 std::ostringstream os;
1350 os << *prefix <<
"Tpetra::DistObject::doTransfer: Done!" << endl;
1351 std::cerr << os.str ();
1355 template <
class Packet,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1357 DistObject<Packet, LocalOrdinal, GlobalOrdinal, Node>::
1358 doPosts(
const Details::DistributorPlan& distributorPlan,
1359 size_t constantNumPackets,
1361 std::shared_ptr<std::string> prefix,
1362 const bool canTryAliasing,
1365 using ::Tpetra::Details::dualViewStatusToString;
1366 using ::Tpetra::Details::getArrayViewFromDualView;
1367 using Kokkos::Compat::create_const_view;
1372 if (constantNumPackets == 0) {
1374 std::ostringstream os;
1375 os << *prefix <<
"7.1. Variable # packets / LID: first comm "
1376 <<
"(commOnHost = " << (commOnHost ?
"true" :
"false") <<
")"
1378 std::cerr << os.str ();
1380 size_t totalImportPackets = 0;
1382 if (this->numExportPacketsPerLID_.need_sync_host ()) {
1383 this->numExportPacketsPerLID_.sync_host ();
1385 if (this->numImportPacketsPerLID_.need_sync_host ()) {
1386 this->numImportPacketsPerLID_.sync_host ();
1388 this->numImportPacketsPerLID_.modify_host ();
1390 create_const_view (this->numExportPacketsPerLID_.view_host ());
1391 auto numImp_h = this->numImportPacketsPerLID_.view_host ();
1395 std::ostringstream os;
1396 os << *prefix <<
"Call doPostsAndWaits"
1398 std::cerr << os.str ();
1400 distributorActor_.doPostsAndWaits(distributorPlan, numExp_h, 1, numImp_h);
1403 std::ostringstream os;
1404 os << *prefix <<
"Count totalImportPackets" << std::endl;
1405 std::cerr << os.str ();
1407 using the_dev_type =
typename decltype (numImp_h)::device_type;
1408 totalImportPackets = countTotalImportPackets<the_dev_type> (numImp_h);
1411 this->numExportPacketsPerLID_.sync_device ();
1412 this->numImportPacketsPerLID_.sync_device ();
1413 this->numImportPacketsPerLID_.modify_device ();
1414 auto numExp_d = create_const_view
1415 (this->numExportPacketsPerLID_.view_device ());
1416 auto numImp_d = this->numImportPacketsPerLID_.view_device ();
1420 std::ostringstream os;
1421 os << *prefix <<
"Call doPostsAndWaits"
1423 std::cerr << os.str ();
1426 distributorActor_.doPostsAndWaits(distributorPlan, numExp_d, 1, numImp_d);
1429 std::ostringstream os;
1430 os << *prefix <<
"Count totalImportPackets" << std::endl;
1431 std::cerr << os.str ();
1433 using the_dev_type =
typename decltype (numImp_d)::device_type;
1434 totalImportPackets = countTotalImportPackets<the_dev_type> (numImp_d);
1438 std::ostringstream os;
1439 os << *prefix <<
"totalImportPackets=" << totalImportPackets << endl;
1440 std::cerr << os.str ();
1442 this->reallocImportsIfNeeded (totalImportPackets, verbose,
1443 prefix.get (), canTryAliasing, CM);
1445 std::ostringstream os;
1446 os << *prefix <<
"7.3. Second comm" << std::endl;
1447 std::cerr << os.str ();
1453 this->numExportPacketsPerLID_.sync_host ();
1454 this->numImportPacketsPerLID_.sync_host ();
1463 auto numExportPacketsPerLID_av =
1465 auto numImportPacketsPerLID_av =
1473 this->imports_.clear_sync_state ();
1476 std::ostringstream os;
1477 os << *prefix <<
"Comm on "
1478 << (commOnHost ?
"host" :
"device")
1479 <<
"; call doPosts" << endl;
1480 std::cerr << os.str ();
1484 this->imports_.modify_host ();
1485 distributorActor_.doPosts
1487 create_const_view (this->exports_.view_host ()),
1488 numExportPacketsPerLID_av,
1489 this->imports_.view_host (),
1490 numImportPacketsPerLID_av);
1494 this->imports_.modify_device ();
1495 distributorActor_.doPosts
1497 create_const_view (this->exports_.view_device ()),
1498 numExportPacketsPerLID_av,
1499 this->imports_.view_device (),
1500 numImportPacketsPerLID_av);
1505 std::ostringstream os;
1506 os << *prefix <<
"7.1. Const # packets per LID: " << endl
1513 std::cerr << os.str ();
1520 this->imports_.clear_sync_state ();
1523 std::ostringstream os;
1524 os << *prefix <<
"7.2. Comm on "
1525 << (commOnHost ?
"host" :
"device")
1526 <<
"; call doPosts" << endl;
1527 std::cerr << os.str ();
1530 this->imports_.modify_host ();
1531 distributorActor_.doPosts
1533 create_const_view (this->exports_.view_host ()),
1535 this->imports_.view_host ());
1539 this->imports_.modify_device ();
1540 distributorActor_.doPosts
1542 create_const_view (this->exports_.view_device ()),
1544 this->imports_.view_device ());
1549 template <
class Packet,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1551 DistObject<Packet, LocalOrdinal, GlobalOrdinal, Node>::
1552 doPackAndPrepare(
const SrcDistObject& src,
1553 const Kokkos::DualView<const local_ordinal_type*, buffer_device_type>& exportLIDs,
1554 size_t& constantNumPackets)
1556 using Details::ProfilingRegion;
1560 ProfilingRegion region_pp
1561 (
"Tpetra::DistObject::doTransferNew::packAndPrepare");
1562#ifdef HAVE_TPETRA_TRANSFER_TIMERS
1565 Teuchos::TimeMonitor packAndPrepareMon (*packAndPrepareTimer_);
1585 std::ostringstream lclErrStrm;
1586 bool lclSuccess =
false;
1588 this->packAndPrepare (src, exportLIDs, this->exports_,
1589 this->numExportPacketsPerLID_,
1590 constantNumPackets);
1593 catch (std::exception& e) {
1594 lclErrStrm <<
"packAndPrepare threw an exception: "
1595 << endl << e.what();
1598 lclErrStrm <<
"packAndPrepare threw an exception "
1599 "not a subclass of std::exception.";
1601 const char gblErrMsgHeader[] =
"Tpetra::DistObject "
1602 "threw an exception in packAndPrepare on "
1603 "one or more processes in the DistObject's communicator.";
1604 auto comm = getMap()->getComm();
1605 Details::checkGlobalError(std::cerr, lclSuccess,
1606 lclErrStrm.str().c_str(),
1607 gblErrMsgHeader, *comm);
1610 this->packAndPrepare (src, exportLIDs, this->exports_,
1611 this->numExportPacketsPerLID_,
1612 constantNumPackets);
1616 template <
class Packet,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1618 DistObject<Packet, LocalOrdinal, GlobalOrdinal, Node>::
1619 doUnpackAndCombine(
const Kokkos::DualView<const local_ordinal_type*, buffer_device_type>& remoteLIDs,
1620 size_t constantNumPackets,
1623 using Details::ProfilingRegion;
1627 ProfilingRegion region_uc
1628 (
"Tpetra::DistObject::doTransferNew::unpackAndCombine");
1629#ifdef HAVE_TPETRA_TRANSFER_TIMERS
1632 Teuchos::TimeMonitor unpackAndCombineMon (*unpackAndCombineTimer_);
1636 std::ostringstream lclErrStrm;
1637 bool lclSuccess =
false;
1640 this->numImportPacketsPerLID_,
1641 constantNumPackets, CM);
1644 catch (std::exception& e) {
1645 lclErrStrm <<
"unpackAndCombine threw an exception: "
1646 << endl << e.what();
1649 lclErrStrm <<
"unpackAndCombine threw an exception "
1650 "not a subclass of std::exception.";
1652 const char gblErrMsgHeader[] =
"Tpetra::DistObject "
1653 "threw an exception in unpackAndCombine on "
1654 "one or more processes in the DistObject's communicator.";
1655 auto comm = getMap()->getComm();
1656 Details::checkGlobalError(std::cerr, lclSuccess,
1657 lclErrStrm.str().c_str(),
1658 gblErrMsgHeader, *comm);
1662 this->numImportPacketsPerLID_,
1663 constantNumPackets, CM);
1667 template <
class Packet,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1673 const Kokkos::DualView<
1676 const Kokkos::DualView<
1682 template <
class Packet,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1687 const Kokkos::DualView<
1699 template <
class Packet,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1703 (
const Kokkos::DualView<
1717 template <
class Packet,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1720 print (std::ostream&
os)
const
1722 using Teuchos::FancyOStream;
1723 using Teuchos::getFancyOStream;
1725 using Teuchos::rcpFromRef;
1729 this->describe (*
out, Teuchos::VERB_DEFAULT);
1732 template <
class Packet,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1733 std::unique_ptr<std::string>
1738 auto map = this->getMap();
1739 auto comm =
map.is_null() ? Teuchos::null :
map->getComm();
1744 template<
class DistObjectType>
1747 Teuchos::RCP<DistObjectType>&
input,
1748 const Teuchos::RCP<
const Map<
1749 typename DistObjectType::local_ordinal_type,
1750 typename DistObjectType::global_ordinal_type,
1751 typename DistObjectType::node_type>>&
newMap)
1755 input = Teuchos::null;
1759 template<
class DistObjectType>
1763 auto newMap =
input->getMap ()->removeEmptyProcesses ();
1768#define TPETRA_DISTOBJECT_INSTANT(SCALAR, LO, GO, NODE) \
1769 template class DistObject< SCALAR , LO , GO , NODE >;
1773#define TPETRA_DISTOBJECT_INSTANT_CHAR(LO, GO, NODE) \
1774 template class DistObject< char , LO , GO , NODE >;