KokkosBatched::Spr¶
Defined in header: KokkosBatched_Spr.hpp
template <typename ArgUplo, typename ArgTrans>
struct SerialSpr {
template <typename ScalarType, typename XViewType, typename APViewType>
KOKKOS_INLINE_FUNCTION static int invoke(const ScalarType alpha, const XViewType &x, const APViewType &ap);
};
template <typename MemberType, typename ArgUplo, typename ArgTrans>
struct TeamSpr {
template <typename ScalarType, typename XViewType, typename APViewType>
KOKKOS_INLINE_FUNCTION static int invoke(const MemberType &member, const ScalarType alpha, const XViewType &x,
const APViewType &ap);
};
template <typename MemberType, typename ArgUplo, typename ArgTrans>
struct TeamVectorSpr {
template <typename ScalarType, typename XViewType, typename APViewType>
KOKKOS_INLINE_FUNCTION static int invoke(const MemberType &member, const ScalarType alpha, const XViewType &x,
const APViewType &ap);
};
Performs one of the symmetric or hermitian rank-1 operation of matrix \(A\) by vector \(x\) with scaling factor \(alpha\), where \(A\) is stored in packed format.
If
ArgTrans == KokkosBatched::Trans::Transpose, this operation is equivalent to the BLAS routine SSPR (CSPR) or DSPR (ZSPR) for single or double precision for real (complex) symmetric matrix.If
ArgTrans == KokkosBatched::Trans::ConjTranspose, this operation is equivalent to the BLAS routine CHPR or ZHPR for single or double precision for complex hermitian matrix.
Parameters¶
- alpha:
Scaling factor
- x:
On input, \(x\) is a length \(n\) vector.
- ap:
With
ArgUplo == KokkosBatched::Uplo::Upper, the upper triangular part of \(A\) is referenced and updated. WithArgUplo == KokkosBatched::Uplo::Lower, the lower triangular part of \(A\) is referenced and updated. The matrix \(A\) is supplied in the packed format as a length \(n*(n+1)/2\) vector, where \(n\) is the size of the matrix.
Type Requirements¶
MemberTypemust be a Kokkos team member handle (only forTeamSprandTeamVectorSpr)ArgUplomust be one of the following:KokkosBatched::Uplo::Upperto update the upper triangular part of \(A\)KokkosBatched::Uplo::Lowerto update the lower triangular part of \(A\)
ArgTransmust be one of the following:KokkosBatched::Trans::Transposeto perform \(A = A + \alpha (x * x^T)\)KokkosBatched::Trans::ConjTransposeto perform \(A = A + \alpha (x * x^H)\)
ScalarTypemust be a built-in floating point type (float,double,Kokkos::complex<float>,Kokkos::complex<double>)XViewTypemust be a Kokkos View of rank 1 containing a vector \(X\)APViewTypemust be a Kokkos View of rank 1 containing a matrix \(A\) in packed format that satisfiesstd::is_same_v<typename APViewType::value_type, typename APViewType::non_const_value_type>
Example¶
1#include <Kokkos_Core.hpp>
2#include <Kokkos_Random.hpp>
3#include <KokkosBatched_Spr.hpp>
4
5using ExecutionSpace = Kokkos::DefaultExecutionSpace;
6
7/// \brief Example of batched spr
8/// Perform a symmetric rank-1 update of matrix A by vector x, where
9/// A: [[1, -3, -2, 0],
10/// [0, 3, -1, -2],
11/// [0, 0, 9, 5],
12/// [0, 0, 0, 27]]
13/// A_packed: [1, -3, -2, 0, 3, -1, -2, 9, 5, 27]
14/// x: [1, 2, 3, 4]
15/// alpha: 1.5
16///
17/// After, A = A + alpha * (x * x^T), it will give
18/// A: [2.5, 0., 9., 2.5, 8., 22.5, 6., 10., 23., 51.]
19///
20int main(int /*argc*/, char** /*argv*/) {
21 Kokkos::initialize();
22 {
23 using View2DType = Kokkos::View<double**, ExecutionSpace>;
24 const int Nb = 10, n = 4;
25 const int packed_size = n * (n + 1) / 2;
26
27 // Matrix A in packed storage
28 View2DType ap("ap", Nb, packed_size), Ref("Ref", Nb, packed_size);
29
30 // Vector x
31 View2DType x("x", Nb, n);
32
33 // Initialize A and x
34 auto h_ap = Kokkos::create_mirror_view(ap);
35 auto h_x = Kokkos::create_mirror_view(x);
36 auto h_Ref = Kokkos::create_mirror_view(Ref);
37
38 // Upper triangular matrix
39 for (int ib = 0; ib < Nb; ib++) {
40 // Fill vector x
41 for (int i = 0; i < n; i++) {
42 h_x(ib, i) = i + 1;
43 }
44
45 // Fill the matrix A
46 h_ap(ib, 0) = 1;
47 h_ap(ib, 1) = -3;
48 h_ap(ib, 2) = 3;
49 h_ap(ib, 3) = -2;
50 h_ap(ib, 4) = -1;
51 h_ap(ib, 5) = 9;
52 h_ap(ib, 6) = 0;
53 h_ap(ib, 7) = -2;
54 h_ap(ib, 8) = 5;
55 h_ap(ib, 9) = 27;
56
57 h_Ref(ib, 0) = 2.5;
58 h_Ref(ib, 1) = 0;
59 h_Ref(ib, 2) = 9;
60 h_Ref(ib, 3) = 2.5;
61 h_Ref(ib, 4) = 8;
62 h_Ref(ib, 5) = 22.5;
63 h_Ref(ib, 6) = 6;
64 h_Ref(ib, 7) = 10;
65 h_Ref(ib, 8) = 23;
66 h_Ref(ib, 9) = 51;
67 }
68 Kokkos::deep_copy(ap, h_ap);
69 Kokkos::deep_copy(x, h_x);
70
71 // Compute A = A + alpha * (x * x^T)
72 const double alpha = 1.5;
73 ExecutionSpace exec;
74 using policy_type = Kokkos::RangePolicy<ExecutionSpace, Kokkos::IndexType<int>>;
75 policy_type policy{exec, 0, Nb};
76 Kokkos::parallel_for(
77 "syr", policy, KOKKOS_LAMBDA(int ib) {
78 auto sub_ap = Kokkos::subview(ap, ib, Kokkos::ALL);
79 auto sub_x = Kokkos::subview(x, ib, Kokkos::ALL);
80
81 // A = A + alpha * (x * x^T)
82 KokkosBatched::SerialSpr<KokkosBatched::Uplo::Upper, KokkosBatched::Trans::Transpose>::invoke(alpha, sub_x,
83 sub_ap);
84 });
85
86 // Confirm that the results are correct
87 Kokkos::deep_copy(h_ap, ap);
88 bool correct = true;
89 double eps = 1.0e-12;
90 for (int ib = 0; ib < Nb; ib++) {
91 for (int i = 0; i < packed_size; i++) {
92 if (Kokkos::abs(h_ap(ib, i) - h_Ref(ib, i)) > eps) correct = false;
93 }
94 }
95
96 if (correct) {
97 std::cout << "spr works correctly!" << std::endl;
98 }
99 }
100 Kokkos::finalize();
101}
output:
spr works correctly!