Skip to content
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions batched/dense/impl/KokkosBatched_SVD_Serial_Impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,12 @@ KOKKOS_INLINE_FUNCTION int SerialSVD::invoke(SVD_USV_Tag, const AViewType &A, co
Vt.stride(0), Vt.stride(1), sigma.data(), sigma.stride(0), work.data(), tol);
}

// Tell users how much memory the work buffer needs
template <typename AViewType>
KOKKOS_INLINE_FUNCTION static size_t work_size(const AViewType &A) {
return Kokkos::max(A.extent_int(0), A.extent_int(1));
}

// Version which computes only singular values
template <typename AViewType, typename SViewType, typename WViewType>
KOKKOS_INLINE_FUNCTION int SerialSVD::invoke(SVD_S_Tag, const AViewType &A, const SViewType &sigma,
Expand Down
4 changes: 4 additions & 0 deletions batched/dense/src/KokkosBatched_SVD_Decl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,10 @@ struct SerialSVD {
SVD_USV_Tag, const AViewType &A, const UViewType &U, const SViewType &s, const VtViewType &Vt, const WViewType &W,
typename AViewType::const_value_type tol = Kokkos::ArithTraits<typename AViewType::value_type>::zero());

// Get the workspace size required for a given matrix.
template <typename AViewType>
KOKKOS_INLINE_FUNCTION static size_t work_size(const AViewType &A);

// Version which computes only singular values
template <typename AViewType, typename SViewType, typename WViewType>
KOKKOS_INLINE_FUNCTION static int invoke(
Expand Down
17 changes: 16 additions & 1 deletion batched/dense/unit_test/Test_Batched_SerialSVD.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -497,6 +497,21 @@ Kokkos::View<Scalar**, Layout, Device> getTestCase(int testCase) {
Ahost = MatrixHost("A5", m, n);
break;
}
case 6: {
m = 3;
n = 2;
Ahost = MatrixHost("A6", m, n);

Ahost(0, 0) = -1.6175067619642277e-05;
Ahost(1, 0) = -1.6175067619642270e-05;
Ahost(2, 0) = 3.0662409276442540e-21;

Ahost(0, 1) = 1.6175067619642277e-05;
Ahost(1, 1) = -1.6175067619642277e-05;
Ahost(2, 1) = 2.3002860307475551e-21;

break;
}
default: throw std::runtime_error("Test case out of bounds.");
}
Kokkos::View<Scalar**, Layout, Device> A(Ahost.label(), m, n);
Expand All @@ -509,7 +524,7 @@ void testSpecialCases() {
using Matrix = Kokkos::View<Scalar**, Layout, Device>;
using Vector = Kokkos::View<Scalar*, Device>;
using ExecSpace = typename Device::execution_space;
for (int i = 0; i < 6; i++) {
for (int i = 0; i < 7; i++) {
Matrix A = getTestCase<Scalar, Layout, Device>(i);
int m = A.extent(0);
int n = A.extent(1);
Expand Down
6 changes: 6 additions & 0 deletions docs/source/API/batched-index.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
API: Batched
============

.. toctree::
:maxdepth: 2
:hidden:

batched/dense/batched_svd_serial.rst

.. note::

Documentation for the batched algorithms is upcoming.
Expand Down
1 change: 1 addition & 0 deletions example/wiki/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
ADD_SUBDIRECTORY(blas)
ADD_SUBDIRECTORY(sparse)
ADD_SUBDIRECTORY(graph)
ADD_SUBDIRECTORY(batched)
1 change: 1 addition & 0 deletions example/wiki/batched/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ADD_SUBDIRECTORY(dense)
9 changes: 9 additions & 0 deletions example/wiki/batched/dense/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
KOKKOSKERNELS_INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
KOKKOSKERNELS_INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})

KOKKOSKERNELS_INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../../../../test_common)

KOKKOSKERNELS_ADD_EXECUTABLE_AND_TEST(
wiki_batched_dense_svd
SOURCES KokkosBatched_wiki_svd.cpp
)
95 changes: 95 additions & 0 deletions example/wiki/batched/dense/KokkosBatched_wiki_svd.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
#include <iostream>
#include <Kokkos_Core.hpp>
#include <KokkosBatched_SVD_Decl.hpp>

template <class MatInfoType, class MatValuesType, class SingularValuesType, class WorkspaceType, class OffsetType>
struct SVD_functor {
using ExecutionSpace = Kokkos::DefaultExecutionSpace;

MatInfoType mat_info;
MatValuesType mat_values;
SingularValuesType S;
WorkspaceType W;
OffsetType s_offset, w_offset;

SVD_functor(MatInfoType mat_info_, MatValuesType mat_values_, SingularValuesType S_,
WorkspaceType W_, OffsetType s_offset_, OffsetType w_offset_) :
mat_info(mat_info_), mat_values(mat_values_), S(S_), W(W_), s_offset(s_offset_),
w_offset(w_offset_) {}

void KOKKOS_FUNCTION operator()(const int matIdx) const {
Kokkos::View<double**, Kokkos::LayoutLeft, ExecutionSpace, Kokkos::MemoryTraits<Kokkos::Unmanaged>>
A(&mat_values(mat_info(matIdx, 0)), mat_info(matIdx, 1), mat_info(matIdx, 2));
Kokkos::View<double*, ExecutionSpace, Kokkos::MemoryTraits<Kokkos::Unmanaged>>
s(&S(s_offset(matIdx)), s_offset(matIdx + 1) - s_offset(matIdx));
Kokkos::View<double*, ExecutionSpace, Kokkos::MemoryTraits<Kokkos::Unmanaged>>
w(&W(w_offset(matIdx)), w_offset(matIdx + 1) - w_offset(matIdx));

KokkosBatched::SerialSVD::invoke(KokkosBatched::SVD_S_Tag{}, A, s, w);
}
};

int main(int argc, char* argv[]) {
Kokkos::initialize(argc, argv);
{
using ExecutionSpace = Kokkos::DefaultExecutionSpace;

constexpr int numMats = 2;

// We want the following matrices in 1D storage
// using a FORTRAN or column wise ordering.
//
// A1 = [2, 1, 4] A2 = [3, 0]
// [-1, 2, -2] [4, 5]
Kokkos::View<double*, ExecutionSpace> mat_values("values storage", 10);
auto mat_values_h = Kokkos::create_mirror_view(mat_values);
mat_values_h(0) = 2; mat_values_h(2) = 1; mat_values_h(4) = 4;
mat_values_h(1) = -1; mat_values_h(3) = 2; mat_values_h(5) = -2;

mat_values_h(6) = 3; mat_values_h(8) = 0;
mat_values_h(7) = 4; mat_values_h(9) = 5;
Kokkos::deep_copy(mat_values, mat_values_h);

// To help our functor extract matrices from 1D storage,
// we specify offset, numRows and numCols for each matrix.
Kokkos::View<int**, ExecutionSpace> mat_info("matrices info", numMats, 3);
auto mat_info_h = Kokkos::create_mirror_view(mat_info);
mat_info_h(0, 0) = 0; mat_info_h(0, 1) = 2; mat_info_h(0, 2) = 3;
mat_info_h(1, 0) = 6; mat_info_h(1, 1) = 2; mat_info_h(1, 2) = 2;
Kokkos::deep_copy(mat_info, mat_info_h);

Kokkos::View<int*, ExecutionSpace> s_offset("s offsets", 3), w_offset("w offsets", 3);
auto s_offset_h = Kokkos::create_mirror_view(s_offset);
auto w_offset_h = Kokkos::create_mirror_view(w_offset);
for(int matIdx = 0; matIdx < numMats; ++matIdx) {
s_offset_h(matIdx + 1) = s_offset_h(matIdx) + Kokkos::min(mat_info_h(matIdx, 1), mat_info_h(matIdx, 2));
w_offset_h(matIdx + 1) = w_offset_h(matIdx) + Kokkos::max(mat_info_h(matIdx, 1), mat_info_h(matIdx, 2));
}
Kokkos::deep_copy(s_offset, s_offset_h);
Kokkos::deep_copy(w_offset, w_offset_h);

Kokkos::View<double*, ExecutionSpace> S("singular values", 4), W("workspace", 5);

SVD_functor svd_calculator(mat_info, mat_values, S, W, s_offset, w_offset);
Kokkos::parallel_for(numMats, svd_calculator);

auto S_h = Kokkos::create_mirror_view(S);
Kokkos::deep_copy(S_h, S);
if(Kokkos::abs(S_h(0) - 5) > 1e-14) {
std::cout << "Large singular value of the first matrix is " << S_h(0) << "instead of 5!" << std::endl;
}
if(Kokkos::abs(S_h(1) - Kokkos::sqrt(5)) > 1e-14) {
std::cout << "Large singular value of the first matrix is " << S_h(1) << "instead of " << Kokkos::sqrt(5) << "!" << std::endl;
}
if(Kokkos::abs(S_h(2) - Kokkos::sqrt(45)) > 1e-14) {
std::cout << "Large singular value of the first matrix is " << S_h(2) << "instead of " << Kokkos::sqrt(45) << "!" << std::endl;
}
if(Kokkos::abs(S_h(3) - Kokkos::sqrt(5)) > 1e-14) {
std::cout << "Large singular value of the first matrix is " << S_h(3) << "instead of " << Kokkos::sqrt(5) << "!" << std::endl;
}

std::cout << "Singular Values of the first matrix: " << S_h(0) << ", " << S_h(1) << std::endl;
std::cout << "Singular Values of the second matrix: " << S_h(2) << ", " << S_h(3) << std::endl;
}
Kokkos::finalize();
}
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,7 @@ struct teamDotFunctor {

template <class ExecSpace>
static void run(benchmark::State& state) {
const auto m = state.range(0);
const auto repeat = state.range(1);
const auto m = state.range(0);
// Declare type aliases
using Scalar = double;
using MemSpace = typename ExecSpace::memory_space;
Expand Down
Loading