Skip to content

Commit 3b5cd9f

Browse files
committed
[Code] Add sub-vec extraction for cuda backend
1 parent d7ba94d commit 3b5cd9f

File tree

8 files changed

+192
-6
lines changed

8 files changed

+192
-6
lines changed

cubool/sources/core/vector.cpp

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,34 @@ namespace cubool {
8585
}
8686

8787
void Vector::extractSubVector(const VectorBase &otherBase, index i, index nrows, bool checkTime) {
88-
RAISE_ERROR(NotImplemented, "This function is not implemented");
88+
const auto* other = dynamic_cast<const Vector*>(&otherBase);
89+
90+
CHECK_RAISE_ERROR(other != nullptr, InvalidArgument, "Passed vector does not belong to core vector class");
91+
92+
auto bI = i + nrows;
93+
94+
CHECK_RAISE_ERROR(nrows > 0, InvalidArgument, "Cannot extract sub-vector with zero dimension");
95+
CHECK_RAISE_ERROR(bI <= other->getNrows(), InvalidArgument, "Provided sub-vector range must be within matrix bounds");
96+
CHECK_RAISE_ERROR(nrows == this->getNrows(), InvalidArgument, "Result matrix has incompatible size for extracted sub-matrix range");
97+
98+
other->commitCache();
99+
this->releaseCache(); // Values of this vector won't be used any more
100+
101+
if (checkTime) {
102+
TIMER_ACTION(timer, mHnd->extractSubVector(*other->mHnd, i, nrows, false));
103+
104+
LogStream stream(*Library::getLogger());
105+
stream << Logger::Level::Info
106+
<< "Time: " << timer.getElapsedTimeMs() << " ms "
107+
<< "Vector::extractSubVector: "
108+
<< this->getDebugMarker() << " =subvector( "
109+
<< i << ", shape=(" << nrows << ") "
110+
<< other->getDebugMarker() << LogStream::cmt;
111+
112+
return;
113+
}
114+
115+
mHnd->extractSubVector(*other->mHnd, i, nrows, false);
89116
}
90117

91118
void Vector::clone(const VectorBase &otherBase) {

cubool/sources/cuda/cuda_vector.cu

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include <cuda/cuda_vector.hpp>
2626
#include <core/error.hpp>
2727
#include <utils/data_utils.hpp>
28+
#include <limits>
2829

2930
namespace cubool {
3031

@@ -70,8 +71,61 @@ namespace cubool {
7071
}
7172

7273
void CudaVector::extractSubVector(const VectorBase &otherBase, index i, index nrows, bool checkTime) {
73-
RAISE_ERROR(NotImplemented, "This function is not implemented");
74+
const auto* v = dynamic_cast<const CudaVector*>(&otherBase);
7475

76+
CHECK_RAISE_ERROR(v != nullptr, InvalidArgument, "Passed vector does not belong to cuda vector class");
77+
78+
assert(i + nrows <= v->getNrows());
79+
assert(getNrows() == nrows);
80+
assert(nrows > 0);
81+
82+
// If source is empty
83+
if (v->getNvals() == 0) {
84+
mVectorImpl = std::move(VectorImplType(nrows));
85+
return;
86+
}
87+
88+
// If source has too small values
89+
index last = v->mVectorImpl.m_rows_index.back();
90+
if (i > last) {
91+
mVectorImpl = std::move(VectorImplType(nrows));
92+
return;
93+
}
94+
95+
auto& vec = v->mVectorImpl;
96+
97+
thrust::device_vector<index, DeviceAlloc<index>> region(2);
98+
thrust::fill_n(region.begin(), 1, std::numeric_limits<index>::max());
99+
thrust::fill_n(region.begin() + 1, 1, 0);
100+
101+
thrust::for_each(thrust::counting_iterator<index>(0), thrust::counting_iterator<index>(vec.m_vals),
102+
[first = region.data(), size = region.data() + 1,
103+
i = i, last = i + nrows, rowIndex = vec.m_rows_index.data()]
104+
__device__ (index id) {
105+
auto rowId = rowIndex[id];
106+
107+
if (i <= rowId && rowId < last) {
108+
atomicAdd(size.get(), 1);
109+
atomicMin(first.get(), id);
110+
}
111+
});
112+
113+
index resultSize = region.back();
114+
115+
// If no values for result
116+
if (resultSize == 0) {
117+
mVectorImpl = std::move(VectorImplType(nrows));
118+
return;
119+
}
120+
121+
// Copy region to the result
122+
index firstToCopy = region.front();
123+
124+
VectorImplType::container_type result(resultSize);
125+
thrust::copy(vec.m_rows_index.begin() + firstToCopy, vec.m_rows_index.begin() + firstToCopy + resultSize, result.begin());
126+
127+
// Update this impl data
128+
mVectorImpl = std::move(VectorImplType(std::move(result), nrows, resultSize));
75129
}
76130

77131
void CudaVector::clone(const VectorBase &otherBase) {

cubool/sources/cuda/details/sp_vector.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ namespace cubool {
3636
typedef bool value_type;
3737
typedef IndexType index_type;
3838
typedef AllocType alloc_type;
39+
typedef thrust::device_vector<IndexType, AllocType> container_type;
40+
3941

4042
SpVector()
4143
: m_rows_index{}, m_rows{0}, m_vals{0} {}

cubool/tests/CMakeLists.txt

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ target_link_libraries(test_matrix_misc PUBLIC testing)
1313
add_executable(test_matrix_transpose test_matrix_transpose.cpp)
1414
target_link_libraries(test_matrix_transpose PUBLIC testing)
1515

16-
add_executable(test_matrix_extract_sub_matrix test_matrix_extract_sub_matrix.cpp)
17-
target_link_libraries(test_matrix_extract_sub_matrix PUBLIC testing)
16+
add_executable(test_matrix_sub_matrix test_matrix_sub_matrix.cpp)
17+
target_link_libraries(test_matrix_sub_matrix PUBLIC testing)
1818

1919
add_executable(test_matrix_reduce test_matrix_reduce.cpp)
2020
target_link_libraries(test_matrix_reduce PUBLIC testing)
@@ -42,3 +42,6 @@ target_link_libraries(test_vector_mxv PUBLIC testing)
4242

4343
add_executable(test_vector_vxm test_vector_vxm.cpp)
4444
target_link_libraries(test_vector_vxm PUBLIC testing)
45+
46+
add_executable(test_vector_sub_vector test_vector_sub_vector.cpp)
47+
target_link_libraries(test_vector_sub_vector PUBLIC testing)
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
/**********************************************************************************/
2+
/* MIT License */
3+
/* */
4+
/* Copyright (c) 2020, 2021 JetBrains-Research */
5+
/* */
6+
/* Permission is hereby granted, free of charge, to any person obtaining a copy */
7+
/* of this software and associated documentation files (the "Software"), to deal */
8+
/* in the Software without restriction, including without limitation the rights */
9+
/* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell */
10+
/* copies of the Software, and to permit persons to whom the Software is */
11+
/* furnished to do so, subject to the following conditions: */
12+
/* */
13+
/* The above copyright notice and this permission notice shall be included in all */
14+
/* copies or substantial portions of the Software. */
15+
/* */
16+
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR */
17+
/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, */
18+
/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE */
19+
/* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER */
20+
/* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, */
21+
/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE */
22+
/* SOFTWARE. */
23+
/**********************************************************************************/
24+
25+
#include <testing/testing.hpp>
26+
27+
void testVectorExtractSubVector(cuBool_Index m, cuBool_Index N, float density, cuBool_Hints flags) {
28+
cuBool_Vector r, a;
29+
30+
auto ta = testing::Vector::generateSparse(m, density);
31+
32+
ASSERT_EQ(cuBool_Vector_New(&a, m), CUBOOL_STATUS_SUCCESS);
33+
ASSERT_EQ(cuBool_Vector_Build(a, ta.index.data(), ta.nvals, CUBOOL_HINT_VALUES_SORTED), CUBOOL_STATUS_SUCCESS);
34+
35+
for (size_t i = 0; i < N; i++) {
36+
auto k = m / N;
37+
38+
ASSERT_EQ(cuBool_Vector_New(&r, k), CUBOOL_STATUS_SUCCESS);
39+
ASSERT_EQ(cuBool_Vector_ExtractSubVector(r, a, i * k, k, flags), CUBOOL_STATUS_SUCCESS);
40+
41+
auto tr = ta.subVector(i * k, k);
42+
43+
ASSERT_TRUE(tr.areEqual(r));
44+
ASSERT_EQ(cuBool_Vector_Free(r), CUBOOL_STATUS_SUCCESS);
45+
}
46+
47+
ASSERT_EQ(cuBool_Vector_Free(a), CUBOOL_STATUS_SUCCESS);
48+
}
49+
50+
void testRun(cuBool_Index m, float step, cuBool_Hints setup) {
51+
// Setup library
52+
EXPECT_EQ(cuBool_Initialize(setup), CUBOOL_STATUS_SUCCESS);
53+
54+
auto N = 10;
55+
56+
for (size_t i = 0; i < N; i++) {
57+
testVectorExtractSubVector(m, N, 0.1f + step * ((float) i), CUBOOL_HINT_NO);
58+
}
59+
60+
// Finalize library
61+
EXPECT_EQ(cuBool_Finalize(), CUBOOL_STATUS_SUCCESS);
62+
}
63+
64+
TEST(cuBool_Matrix, SubVectorExtractSmall) {
65+
cuBool_Index m = 10000;
66+
float step = 0.05f;
67+
testRun(m, step, CUBOOL_HINT_NO);
68+
}
69+
70+
TEST(cuBool_Matrix, SubVectorExtractMedium) {
71+
cuBool_Index m = 50000;
72+
float step = 0.05f;
73+
testRun(m, step, CUBOOL_HINT_NO);
74+
}
75+
76+
TEST(cuBool_Matrix, SubVectorExtractLarge) {
77+
cuBool_Index m = 100000;
78+
float step = 0.05f;
79+
testRun(m, step, CUBOOL_HINT_NO);
80+
}
81+
82+
TEST(cuBool_Matrix, SubVectorExtractSmallFallback) {
83+
cuBool_Index m = 10000;
84+
float step = 0.05f;
85+
testRun(m, step, CUBOOL_HINT_CPU_BACKEND);
86+
}
87+
88+
TEST(cuBool_Matrix, SubVectorExtractMediumFallback) {
89+
cuBool_Index m = 50000;
90+
float step = 0.05f;
91+
testRun(m, step, CUBOOL_HINT_CPU_BACKEND);
92+
}
93+
94+
TEST(cuBool_Matrix, SubVectorExtractLargeFallback) {
95+
cuBool_Index m = 100000;
96+
float step = 0.05f;
97+
testRun(m, step, CUBOOL_HINT_CPU_BACKEND);
98+
}
99+
100+
CUBOOL_GTEST_MAIN

scripts/run_tests_all.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@
22
# Invoke this script within build directory
33
./cubool/tests/test_library_api
44
./cubool/tests/test_matrix_ewiseadd
5-
./cubool/tests/test_matrix_extract_sub_matrix
65
./cubool/tests/test_matrix_kronecker
76
./cubool/tests/test_matrix_misc
87
./cubool/tests/test_matrix_mxm
98
./cubool/tests/test_matrix_reduce
109
./cubool/tests/test_matrix_setup
10+
./cubool/tests/test_matrix_sub_matrix
1111
./cubool/tests/test_matrix_element
1212
./cubool/tests/test_matrix_transpose
1313
./cubool/tests/test_vector_misc

scripts/run_tests_fallback.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@
33
./cubool/tests/test_library_api
44
./cubool/tests/test_matrix_misc
55
./cubool/tests/test_matrix_ewiseadd --gtest_filter=*.*Fallback
6-
./cubool/tests/test_matrix_extract_sub_matrix --gtest_filter=*.*Fallback
76
./cubool/tests/test_matrix_kronecker --gtest_filter=*.*Fallback
87
./cubool/tests/test_matrix_mxm --gtest_filter=*.*Fallback
98
./cubool/tests/test_matrix_reduce --gtest_filter=*.*Fallback
109
./cubool/tests/test_matrix_setup --gtest_filter=*.*Fallback
10+
./cubool/tests/test_matrix_sub_matrix --gtest_filter=*.*Fallback
1111
./cubool/tests/test_matrix_element --gtest_filter=*.*Fallback
1212
./cubool/tests/test_matrix_transpose --gtest_filter=*.*Fallback
1313
./cubool/tests/test_vector_misc

0 commit comments

Comments
 (0)