189 using TeamPolicy = Kokkos::TeamPolicy<MemorySpace>;
190 using MemberType =
typename TeamPolicy::member_type;
191 using ScratchView = Kokkos::View<double *, typename MemorySpace::scratch_memory_space, UnmanagedMemory>;
194 Kokkos::deep_copy(qrMatrix, 1.0);
197 auto kernel = KOKKOS_LAMBDA(
const MemberType &team)
200 const int batch = team.league_rank();
203 const auto begin = offsets(batch);
204 const int verticesPerCluster = offsets(batch + 1) - begin;
205 const int matrixCols = dim + 1;
211 Kokkos::parallel_for(
212 Kokkos::TeamThreadRange(team, verticesPerCluster),
214 auto globalID = globalIDs(i + begin);
216 for (
int d = 0; d < dim; ++d) {
217 qr(i, d) =
mesh(globalID, d);
230 int &rank = qrP(PBegin + matrixCols);
233 ScratchView work(team.team_scratch(0), 2 * verticesPerCluster);
239 KokkosBatched::TeamVectorQR_WithColumnPivoting<MemberType,
240 KokkosBatched::Algo::QR::Unblocked>::invoke(team, qr, tau,
249 double threshold = 1e-5;
250 if (team.team_rank() == 0) {
251 const double maxp = Kokkos::abs(qr(0, 0));
253 for (
int i = 0; i < rank; ++i) {
254 r +=
static_cast<int>(Kokkos::abs(qr(i, i)) > (threshold * maxp));
264 auto scratchSize = ScratchView::shmem_size(2 * maxClusterSize);
268 std::unique_ptr<TeamPolicy> policy;
269 if constexpr (std::is_same_v<
decltype(teamSize), Kokkos::AUTO_t>) {
270 policy = std::make_unique<TeamPolicy>(nCluster, Kokkos::AUTO);
272 policy = std::make_unique<TeamPolicy>(nCluster, 4, teamSize / 4);
274 policy->set_scratch_size( 0, Kokkos::PerTeam(scratchSize));
275 Kokkos::parallel_for(
"do_batched_qr", *policy,
kernel);
495 int avgInClusterSize,
496 int maxInClusterSize,
497 int maxOutClusterSize,
517 using ExecSpace =
typename MemorySpace::execution_space;
518 using TeamPolicy = Kokkos::TeamPolicy<ExecSpace>;
519 using MemberType =
typename TeamPolicy::member_type;
521 using ScratchSpace =
typename MemorySpace::scratch_memory_space;
525 using ScratchView1d = Kokkos::View<double *[1], Kokkos::LayoutLeft, ScratchSpace, UnmanagedMemory>;
526 using ScratchView4d = Kokkos::View<double *[4], Kokkos::LayoutLeft, ScratchSpace, UnmanagedMemory>;
527 using ScratchVector = Kokkos::View<double *, ScratchSpace, UnmanagedMemory>;
528 using ScratchMatrix = std::conditional_t<!evaluation_op_available || polynomial, ScratchView4d, ScratchView1d>;
529 using ScratchMesh = Kokkos::View<double **, Kokkos::LayoutRight, ScratchSpace, UnmanagedMemory>;
531 const auto rbf_params = f.getFunctionParameters();
534 auto kernel = KOKKOS_LAMBDA(
const MemberType &team)
537 impl::capture_conditional_variables(dim, qrMatrix, qrTau, qrP, inMesh, outMesh, evalOffsets, evalMat, globalOutIDs, f, rbf_params, normalizedWeights, out);
541 const int batch = team.league_rank();
542 const auto inBegin = rhsOffsets(batch);
543 const int inSize = rhsOffsets(batch + 1) - inBegin;
544 const auto outBegin = outOffsets(batch);
545 const int outSize = outOffsets(batch + 1) - outBegin;
549 ScratchMatrix work(team.team_scratch(0), Kokkos::max(4, inSize));
550 auto in = Kokkos::subview(work, Kokkos::pair<int, int>(0, inSize), 0);
552 Kokkos::parallel_for(
553 Kokkos::TeamThreadRange(team, inSize), [&](
int i) {
554 auto globalID = globalRhsIDs(i + inBegin);
555 in(i) = rhs(globalID);
559 Kokkos::Array<double, 4> qrCoeffs = {0., 0., 0., 0.};
562 if constexpr (polynomial) {
567 auto in_cp = Kokkos::subview(work, Kokkos::pair<int, int>(0, inSize), Kokkos::pair<int, int>(1, 2));
568 Kokkos::parallel_for(
569 Kokkos::TeamThreadRange(team, inSize), [&](
int i) { in_cp(i, 0) = in(i); });
573 const int matrixCols = dim + 1;
577 const int rank = qrP(PBegin + matrixCols);
584 if (team.team_rank() == 0) {
588 auto tmp = Kokkos::subview(work, Kokkos::ALL, 2);
589 KokkosBatched::ApplyQ<MemberType,
590 KokkosBatched::Side::Left,
591 KokkosBatched::Trans::Transpose,
592 KokkosBatched::Mode::Serial,
593 KokkosBatched::Algo::ApplyQ::Unblocked>::invoke(team, qr, tau, in_cp, tmp);
596 auto in_r = Kokkos::subview(in_cp, Kokkos::pair<int, int>(0, rank), 0);
597 auto R = Kokkos::subview(qr, Kokkos::pair<int, int>(0, rank), Kokkos::pair<int, int>(0, rank));
601 KokkosBatched::Uplo::Upper,
602 KokkosBatched::Trans::NoTranspose,
603 KokkosBatched::Diag::NonUnit,
604 KokkosBatched::Mode::Serial,
605 KokkosBatched::Algo::Trsv::Unblocked>::invoke(team, 1.0, R, in_r);
611 for (
int r = 0; r < rank; ++r) {
612 qrCoeffs[r] = in_cp(r, 0);
620 for (
int i = (matrixCols - 1); i >= 0; --i) {
621 Kokkos::kokkos_swap(qrCoeffs[i], qrCoeffs[i + P(i)]);
636 ScratchMesh localInMesh;
638 if constexpr (!evaluation_op_available || polynomial) {
639 localInMesh = ScratchMesh(&work(0, 1), inSize, dim);
641 Kokkos::parallel_for(
642 Kokkos::TeamThreadRange(team, inSize),
644 auto globalID = globalRhsIDs(i + inBegin);
647 double sum = qrCoeffs[dim];
649 for (
int d = 0; d < dim; ++d) {
650 sum += inMesh(globalID, d) * qrCoeffs[d];
652 localInMesh(i, d) = inMesh(globalID, d);
663 auto matStart = matrixOffsets(batch);
669 KokkosBatched::Uplo::Lower,
670 KokkosBatched::Trans::NoTranspose,
671 KokkosBatched::Diag::Unit,
672 KokkosBatched::Mode::Team,
673 KokkosBatched::Algo::Trsv::Blocked>::invoke(team, 1.0, A, in);
680 KokkosBatched::Uplo::Upper,
681 KokkosBatched::Trans::NoTranspose,
682 KokkosBatched::Diag::NonUnit,
683 KokkosBatched::Mode::Team,
684 KokkosBatched::Algo::Trsv::Blocked>::invoke(team, 1.0, A, in);
689 if constexpr (evaluation_op_available) {
691 ScratchVector res(team.team_scratch(1), outSize);
692 Kokkos::parallel_for(
693 Kokkos::TeamThreadRange(team, outSize),
694 [&](
int i) { res(i) = 0; });
699 auto startEval = evalOffsets(batch);
702 KokkosBlas::Experimental::Gemv<
703 KokkosBlas::Mode::Team,
704 KokkosBlas::Algo::Gemv::Blocked>::invoke(team,
'N', 1.0, eval, in, 0.0, res);
710 Kokkos::parallel_for(
711 Kokkos::TeamThreadRange(team, outSize),
713 auto globalID = globalOutIDs(i + outBegin);
716 if constexpr (polynomial) {
719 sum += qrCoeffs[dim];
721 for (
int d = 0; d < dim; ++d) {
722 sum += outMesh(globalID, d) * qrCoeffs[d];
725 auto w = normalizedWeights(i + outBegin);
726 Kokkos::atomic_add(&out(globalID), sum * w);
731 Kokkos::parallel_for(
732 Kokkos::TeamThreadRange(team, outSize), [&](
int r) {
733 auto globalID = globalOutIDs(r + outBegin);
736 Kokkos::Array<double, 3> outVertex = {0., 0., 0.};
737 for (
int d = 0; d < dim; ++d) {
738 outVertex[d] = outMesh(globalID, d);
744 Kokkos::parallel_reduce(
745 Kokkos::ThreadVectorRange(team, inSize),
746 [&](
int c,
double &localSum) {
749 for (
int d = 0; d < dim; ++d) {
750 double diff = outVertex[d] - localInMesh(c, d);
753 dist = Kokkos::sqrt(dist);
755 double val = f(dist, rbf_params);
756 localSum += val * in(c);
761 if constexpr (polynomial) {
764 sum += qrCoeffs[dim];
766 for (
int d = 0; d < dim; ++d) {
767 sum += outVertex[d] * qrCoeffs[d];
771 auto w = normalizedWeights(r + outBegin);
772 Kokkos::atomic_add(&out(globalID), sum * w);
781 auto inBytes = ScratchVector::shmem_size(std::max(4, maxInClusterSize));
782 auto outBytes = ScratchVector::shmem_size(maxOutClusterSize);
783 if (!evaluation_op_available || polynomial) {
785 inBytes = 4 * inBytes;
789 if (!evaluation_op_available) {
796 auto tmpPol = TeamPolicy(nCluster, Kokkos::AUTO)
798 0, Kokkos::PerTeam(inBytes))
800 1, Kokkos::PerTeam(outBytes));
804 auto policy = TeamPolicy(nCluster, teamSize)
806 0, Kokkos::PerTeam(inBytes))
808 1, Kokkos::PerTeam(outBytes));
810 Kokkos::parallel_for(
"do_batched_solve", policy,
kernel);
822 int avgInClusterSize,
823 int maxInClusterSize,
824 int maxOutClusterSize,
844 using ExecSpace =
typename MemorySpace::execution_space;
845 using TeamPolicy = Kokkos::TeamPolicy<ExecSpace>;
846 using MemberType =
typename TeamPolicy::member_type;
848 using ScratchSpace =
typename MemorySpace::scratch_memory_space;
852 using ScratchView1d = Kokkos::View<double *[1], Kokkos::LayoutLeft, ScratchSpace, UnmanagedMemory>;
853 using ScratchView4d = Kokkos::View<double *[4], Kokkos::LayoutLeft, ScratchSpace, UnmanagedMemory>;
854 using ScratchView3d = Kokkos::View<double *[3], Kokkos::LayoutLeft, ScratchSpace, UnmanagedMemory>;
855 using ScratchVector = Kokkos::View<double *, ScratchSpace, UnmanagedMemory>;
856 using ScratchMatrix4 = std::conditional_t<!evaluation_op_available || polynomial, ScratchView4d, ScratchView1d>;
857 using ScratchMatrix3 = std::conditional_t<!evaluation_op_available || polynomial, ScratchView3d, ScratchView1d>;
858 using ScratchMesh = Kokkos::View<double **, Kokkos::LayoutRight, ScratchSpace, UnmanagedMemory>;
860 const auto rbf_params = f.getFunctionParameters();
863 auto kernel = KOKKOS_LAMBDA(
const MemberType &team)
866 impl::capture_conditional_variables(dim, qrMatrix, qrTau, qrP, inMesh, outMesh, evalOffsets, evalMat, globalOutIDs, f, rbf_params, normalizedWeights, src, globalRhsIDs);
869 const int batch = team.league_rank();
871 const auto inBegin = rhsOffsets(batch);
872 const int inSize = rhsOffsets(batch + 1) - inBegin;
874 const auto outBegin = outOffsets(batch);
875 const int outSize = outOffsets(batch + 1) - outBegin;
879 ScratchMatrix3 work(team.team_scratch(0), Kokkos::max(4, inSize));
880 auto Au = Kokkos::subview(work, std::pair<int, int>(0, inSize), 0);
885 ScratchMatrix4 localIn(team.team_scratch(1), outSize);
886 auto in = Kokkos::subview(localIn, std::pair<int, int>(0, outSize), 0);
887 ScratchMesh localMesh;
889 if constexpr (!evaluation_op_available || polynomial)
890 localMesh = ScratchMesh(&localIn(0, 1), outSize, dim);
893 Kokkos::parallel_for(
894 Kokkos::TeamThreadRange(team, outSize), [&](
int r) {
895 auto globalID = globalOutIDs(r + outBegin);
896 auto w = normalizedWeights(r + outBegin);
897 in(r) = src(globalID) * w;
899 if constexpr (!evaluation_op_available || polynomial) {
900 for (
int d = 0; d < dim; ++d)
901 localMesh(r, d) = outMesh(globalID, d);
907 if constexpr (evaluation_op_available) {
908 auto startEval = evalOffsets(batch);
911 KokkosBlas::Experimental::Gemv<
912 KokkosBlas::Mode::Team,
913 KokkosBlas::Algo::Gemv::Blocked>::invoke(team,
'T', 1.0, eval, in, 0.0, Au);
925 Kokkos::parallel_for(
926 Kokkos::TeamThreadRange(team, inSize), [&](
int r) {
927 auto globalRhsID = globalRhsIDs(r + inBegin);
928 Kokkos::Array<double, 3> vertex = {0., 0., 0.};
929 for (
int d = 0; d < dim; ++d) {
930 vertex[d] = inMesh(globalRhsID, d);
934 Kokkos::parallel_reduce(
935 Kokkos::ThreadVectorRange(team, outSize),
936 [&](
int c,
double &localSum) {
939 for (
int d = 0; d < dim; ++d) {
940 double diff = vertex[d] - localMesh(c, d);
943 dist = Kokkos::sqrt(dist);
945 double val = f(dist, rbf_params);
946 localSum += val * in(c);
963 auto matStart = matrixOffsets(batch);
969 KokkosBatched::Uplo::Lower,
970 KokkosBatched::Trans::NoTranspose,
971 KokkosBatched::Diag::Unit,
972 KokkosBatched::Mode::Team,
973 KokkosBatched::Algo::Trsv::Blocked>::invoke(team, 1.0, A, Au);
980 KokkosBatched::Uplo::Upper,
981 KokkosBatched::Trans::NoTranspose,
982 KokkosBatched::Diag::NonUnit,
983 KokkosBatched::Mode::Team,
984 KokkosBatched::Algo::Trsv::Blocked>::invoke(team, 1.0, A, Au);
988 ScratchView1d qrSolution;
989 if constexpr (polynomial) {
990 qrSolution = Kokkos::subview(work, std::pair<int, int>(0, inSize), std::pair<int, int>(1, 2));
992 if constexpr (polynomial) {
993 Kokkos::parallel_reduce(
994 Kokkos::TeamThreadRange(team, outSize),
995 [&](
const int c,
double &s0,
double &s1,
double &s2,
double &s3) {
996 const double tmp = in(c);
999 s0 += localMesh(c, 0) * tmp;
1000 s1 += localMesh(c, 1) * tmp;
1002 s2 += localMesh(c, 2) * tmp;
1005 qrSolution(0, 0), qrSolution(1, 0), qrSolution(2, 0), qrSolution(3, 0));
1007 team.team_barrier();
1011 auto tmp = Kokkos::subview(work, Kokkos::ALL(), 2);
1013 Kokkos::parallel_reduce(
1014 Kokkos::TeamThreadRange(team, inSize),
1015 [&](
const int k,
double &s0,
double &s1,
double &s2,
double &s3) {
1016 const double val = Au(k);
1017 auto globalID = globalRhsIDs(k + inBegin);
1019 s0 += inMesh(globalID, 0) * val;
1020 s1 += inMesh(globalID, 1) * val;
1022 s2 += inMesh(globalID, 2) * val;
1025 tmp(0), tmp(1), tmp(2), tmp(3));
1028 Kokkos::single(Kokkos::PerTeam(team), [&] {
1029 for (
int d = 0; d < dim; ++d) {
1030 tmp(d) -= qrSolution(d, 0);
1032 tmp(dim) = tmp(3) - qrSolution(3, 0);
1035 team.team_barrier();
1038 const int matrixCols = dim + 1;
1042 const int rank = qrP(PBegin + matrixCols);
1049 Kokkos::parallel_for(
1050 Kokkos::TeamThreadRange(team, inSize), [&](
int i) { qrSolution(i, 0) = 0; });
1051 team.team_barrier();
1053 if (team.team_rank() == 0) {
1056 auto R = Kokkos::subview(qr, std::pair<int, int>(0, rank), std::pair<int, int>(0, rank));
1057 auto rhs_re = Kokkos::subview(qrSolution, std::pair<int, int>(0, matrixCols), 0);
1059 for (
int i = 0; i < matrixCols; ++i) {
1062 KokkosBatched::TeamVectorApplyPivot<MemberType,
1063 KokkosBatched::Side::Left,
1064 KokkosBatched::Direct::Forward>::invoke(team, P, rhs_re);
1066 auto rhs_r = Kokkos::subview(qrSolution, std::pair<int, int>(0, rank), 0);
1069 KokkosBatched::Trsv<
1071 KokkosBatched::Uplo::Upper,
1072 KokkosBatched::Trans::Transpose,
1073 KokkosBatched::Diag::NonUnit,
1074 KokkosBatched::Mode::Serial,
1075 KokkosBatched::Algo::Trsv::Unblocked>::invoke(team, 1.0, R, rhs_r);
1078 KokkosBatched::ApplyQ<MemberType,
1079 KokkosBatched::Side::Left,
1080 KokkosBatched::Trans::NoTranspose,
1081 KokkosBatched::Mode::Serial,
1082 KokkosBatched::Algo::ApplyQ::Unblocked>::invoke(team, qr, tau, qrSolution, tmp);
1085 team.team_barrier();
1089 Kokkos::parallel_for(
1090 Kokkos::TeamThreadRange(team, inSize), [&](
int i) {
1091 auto globalID = globalRhsIDs(i + inBegin);
1093 if constexpr (polynomial) {
1095 val -= qrSolution(i, 0);
1097 Kokkos::atomic_add(&rhsdst(globalID), val);
1104 auto inBytes = ScratchVector::shmem_size(std::max(4, maxInClusterSize));
1105 auto outBytes = ScratchVector::shmem_size(maxOutClusterSize);
1108 inBytes = 3 * inBytes;
1113 if (!evaluation_op_available || polynomial) {
1114 outBytes = 4 * outBytes;
1120 auto tmpPol = TeamPolicy(nCluster, Kokkos::AUTO)
1122 0, Kokkos::PerTeam(inBytes))
1124 1, Kokkos::PerTeam(outBytes));
1128 auto policy = TeamPolicy(nCluster, teamSize)
1130 0, Kokkos::PerTeam(inBytes))
1132 1, Kokkos::PerTeam(outBytes));
1134 Kokkos::parallel_for(
"do_batched_conservative_solve", policy,
kernel);
1143 int maxInClusterSize,
1157 using TeamPolicy = Kokkos::TeamPolicy<MemorySpace>;
1158 using MemberType =
typename TeamPolicy::member_type;
1159 using ScratchView = Kokkos::View<double *[2], typename MemorySpace::scratch_memory_space, UnmanagedMemory>;
1162 auto scratchSize = ScratchView::shmem_size(2 * maxInClusterSize);
1163 Kokkos::parallel_for(
"do_qr_solve", TeamPolicy(nCluster, Kokkos::AUTO).set_scratch_size(
1164 0, Kokkos::PerTeam(scratchSize)),
1165 KOKKOS_LAMBDA(
const MemberType &team) {
1167 const int batch = team.league_rank();
1169 const auto inBegin = inOffsets(batch);
1170 const auto inEnd = inOffsets(batch + 1);
1171 const int inSize = inEnd - inBegin;
1172 const auto outBegin = outOffsets(batch);
1173 const auto outEnd = outOffsets(batch + 1);
1174 const int outSize = outEnd - outBegin;
1177 ScratchView tmp(team.team_scratch(0), inSize, 2);
1178 auto in = Kokkos::subview(tmp, Kokkos::ALL, 0);
1179 auto work = Kokkos::subview(tmp, Kokkos::ALL, 1);
1181 Kokkos::parallel_for(
1182 Kokkos::TeamThreadRange(team, inSize),
1184 auto globalID = globalInIDs(i + inBegin);
1185 in(i) = inData(globalID);
1188 team.team_barrier();
1191 const int matrixCols = dim + 1;
1195 const int rank = qrP(PBegin + matrixCols);
1204 KokkosBatched::TeamVectorApplyQ<MemberType,
1205 KokkosBatched::Side::Left,
1206 KokkosBatched::Trans::Transpose,
1207 KokkosBatched::Algo::ApplyQ::Unblocked>::invoke(team, qr, tau, in, work);
1208 team.team_barrier();
1210 auto in_r = Kokkos::subview(in, Kokkos::pair<int, int>(0, rank));
1211 auto R = Kokkos::subview(qr, Kokkos::pair<int, int>(0, rank), Kokkos::pair<int, int>(0, rank));
1214 KokkosBatched::Trsv<
1216 KokkosBatched::Uplo::Upper,
1217 KokkosBatched::Trans::NoTranspose,
1218 KokkosBatched::Diag::NonUnit,
1219 KokkosBatched::Mode::Team,
1220 KokkosBatched::Algo::Trsv::Blocked>::invoke(team, 1.0, R, in_r);
1221 team.team_barrier();
1223 auto res = Kokkos::subview(in, Kokkos::pair<int, int>(0, matrixCols));
1226 Kokkos::parallel_for(
1227 Kokkos::TeamThreadRange(team, rank, matrixCols), [&](
int i) { res(i) = 0; });
1229 team.team_barrier();
1232 KokkosBatched::TeamVectorApplyPivot<MemberType,
1233 KokkosBatched::Side::Left,
1234 KokkosBatched::Direct::Backward>::invoke(team, P, res);
1235 team.team_barrier();
1239 Kokkos::parallel_for(
1240 Kokkos::TeamThreadRange(team, inBegin, inEnd),
1242 auto globalID = globalInIDs(i);
1245 double tmp = res(matrixCols - 1);
1247 for (
int d = 0; d < dim; ++d)
1248 tmp += inMesh(globalID, d) * res(d);
1250 Kokkos::atomic_sub(&inData(globalID), tmp);
1256 Kokkos::parallel_for(
1257 Kokkos::TeamThreadRange(team, outBegin, outEnd),
1259 auto globalID = globalOutIDs(i);
1262 double tmp = res(matrixCols - 1);
1264 for (
int d = 0; d < dim; ++d)
1265 tmp += outMesh(globalID, d) * res(d);
1268 double w = weights(i);
1269 Kokkos::atomic_add(&outData(globalID), tmp * w);