Skip to content

Commit 95962f6

Browse files
committed
Streamlined the handling of non-empty blocks of sparse LHS vectors.
1 parent 6fb44de commit 95962f6

4 files changed

Lines changed: 22 additions & 30 deletions

File tree

include/tatami_mult/dense_matrix/sparse_column/column_to_column.hpp

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -131,15 +131,12 @@ void multiply_sparse_column_with_dense_column_matrix_to_column_output(
131131
options.block_size,
132132
/* zero = */ [&](const LeftIndex_) -> void {} // buffers should already be zeroed.
133133
);
134-
cd = left_block_info.position;
135-
136134
const auto cd_num = left_block_info.num_non_empty;
137-
if (cd_num == 0) {
138-
break;
139-
}
140135

141-
if (left_block_info.consecutive) {
142-
const LeftIndex_ cd_base = start + left_non_empty.front();
136+
// If the LHS rows are all non-empty, we can speed up the loops by just using a simple counter to get the column indices.
137+
// Otherwise, we'll have to access the 'left_non_empty' vector to figure out the indices of each non-empty column.
138+
if (left_block_info.all_non_empty) {
139+
const LeftIndex_ cd_base = cd + start;
143140
for (RightIndex_ rc = 0; rc < right_NC; ++rc) {
144141
const auto rightcol = right_ptrs[rc];
145142
for (LeftIndex_ cd_counter = 0; cd_counter < cd_num; ++cd_counter) {
@@ -166,6 +163,8 @@ void multiply_sparse_column_with_dense_column_matrix_to_column_output(
166163
}
167164
}
168165
}
166+
167+
cd = left_block_info.position;
169168
}
170169
}
171170

include/tatami_mult/dense_matrix/sparse_row/column_to_row.hpp

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -123,18 +123,12 @@ void multiply_sparse_row_with_dense_column_matrix_to_row_output(
123123
std::fill_n(output + sanisizer::product_unsafe<std::size_t>(start + lr_copy, right_NC), right_NC, 0);
124124
}
125125
);
126-
lr = left_block_info.position;
127-
128126
const auto lr_num = left_block_info.num_non_empty;
129-
if (lr_num == 0) {
130-
break;
131-
}
132127

133-
// If the LHS columns are consecutive, we can speed up the loops by just using a simple counter to get the column indices.
128+
// If the LHS columns are all non-empty, we can speed up the loops by just using a simple counter to get the column indices.
134129
// Otherwise, we'll have to access the 'left_non_empty' vector to figure out the indices of each non-empty column.
135-
if (left_block_info.consecutive) {
136-
const auto lr_base = start + left_non_empty.front();
137-
130+
if (left_block_info.all_non_empty) {
131+
const auto lr_base = lr + start;
138132
// Yes, we deliberately iterate over the RHS columns in the outer loop to keep the dense column in cache across multiple LHS vectors.
139133
// If we did it the other way around, this would defeat the purpose of blocking.
140134
for (RightIndex_ rc = 0; rc < right_NC; ++rc) {
@@ -169,6 +163,8 @@ void multiply_sparse_row_with_dense_column_matrix_to_row_output(
169163
}
170164
}
171165
}
166+
167+
lr = left_block_info.position;
172168
}
173169
}, left_NR, options.num_threads);
174170
}

include/tatami_mult/multiple_vectors/sparse_column.hpp

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -144,17 +144,12 @@ void multiply_sparse_column_with_multiple_vectors(
144144
options.block_size,
145145
/* zero = */ [](Index_) -> void {} // (No need to worry about zeroing as the buffers have already been zeroed.)
146146
);
147-
cd = left_block_info.position;
148-
149147
const auto cd_num = left_block_info.num_non_empty;
150-
if (cd_num == 0) {
151-
break;
152-
}
153148

154-
// If the LHS columns are consecutive, we can speed up the loops by just using a simple counter to get the column indices.
149+
// If the LHS columns are all non-empty, we can speed up the loops by just using a simple counter to get the column indices.
155150
// Otherwise, we'll have to access the 'left_non_empty' vector to figure out the indices of each non-empty column.
156-
if (left_block_info.consecutive) {
157-
const Index_ cd_base = start + left_non_empty.front();
151+
if (left_block_info.all_non_empty) {
152+
const Index_ cd_base = start + cd;
158153
for (RightIndex rc = 0; rc < right_NC; ++rc) {
159154
const auto outcol = outptrs[rc];
160155
const auto rightcol = right[rc];
@@ -183,6 +178,8 @@ void multiply_sparse_column_with_multiple_vectors(
183178
}
184179
}
185180
}
181+
182+
cd = left_block_info.position;
186183
}
187184
}
188185

include/tatami_mult/utils.hpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,10 @@ void populate_dense_buffers(
4242

4343
template<typename Index_>
4444
struct FetchNonEmptySparseBlockInfo {
45-
FetchNonEmptySparseBlockInfo(const Index_ position, const Index_ num_non_empty, const bool consecutive) :
46-
position(position), num_non_empty(num_non_empty), consecutive(consecutive) {}
45+
FetchNonEmptySparseBlockInfo(const Index_ position, const Index_ num_non_empty, const bool all_non_empty) :
46+
position(position), num_non_empty(num_non_empty), all_non_empty(all_non_empty) {}
4747
Index_ position, num_non_empty;
48-
bool consecutive;
48+
bool all_non_empty;
4949
};
5050

5151
template<typename Value_, typename Index_, class Zero_>
@@ -62,7 +62,7 @@ FetchNonEmptySparseBlockInfo<Index_> fetch_non_empty_sparse_block(
6262
) {
6363
non_empty.clear();
6464
Index_ num_non_empty = 0;
65-
bool consecutive = true;
65+
bool all_non_empty = true;
6666

6767
// We assume that a check for remaining dimension elements was performed before continuing the blocked loop.
6868
assert(position < length);
@@ -71,7 +71,7 @@ FetchNonEmptySparseBlockInfo<Index_> fetch_non_empty_sparse_block(
7171
auto lrange = ext.fetch(vbuffers[num_non_empty].data(), ibuffers[num_non_empty].data());
7272
if (lrange.number == 0) {
7373
zero(position);
74-
consecutive = false;
74+
all_non_empty = false;
7575
++position;
7676
continue;
7777
}
@@ -86,7 +86,7 @@ FetchNonEmptySparseBlockInfo<Index_> fetch_non_empty_sparse_block(
8686
}
8787
} while (position < length);
8888

89-
return FetchNonEmptySparseBlockInfo(position, num_non_empty, consecutive);
89+
return FetchNonEmptySparseBlockInfo(position, num_non_empty, all_non_empty);
9090
}
9191

9292
template<typename Output_, typename DenseValue_, typename Value_, typename Index_>

0 commit comments

Comments
 (0)