| 1242 | |
| 1243 | template <typename TL, typename TR> |
| 1244 | inline BlockingCounter* SparseMatMul<TL, TR>::ShuffleMatrix( |
| 1245 | const typename SparseMatMul<TL, TR>::ConstMatrixMapR& mat, |
| 1246 | int slice_row_start, int slice_num_rows, int slice_col_start, |
| 1247 | int slice_num_cols, const int N, |
| 1248 | const DeviceBase::CpuWorkerThreads* thread_pool, MatrixR* buffer) { |
| 1249 | DCHECK_EQ(N % 2, 0); |
| 1250 | DCHECK_LE(kNumOperands * sizeof(float) / sizeof(TR), N); |
| 1251 | int num_threads = std::min(thread_pool->num_threads, 16); |
| 1252 | BlockingCounter* counter = new BlockingCounter(num_threads); |
| 1253 | DCHECK_EQ(N, buffer->dimension(1)); |
| 1254 | auto shuffle_work = [&mat, slice_row_start, slice_num_rows, slice_col_start, |
| 1255 | slice_num_cols, N, buffer, counter](int s, int e) { |
| 1256 | const int row_start = s % slice_num_rows + slice_row_start; |
| 1257 | const int col_start = s / slice_num_rows * N + slice_col_start; |
| 1258 | auto* out_start = &(*buffer)(s, 0); |
| 1259 | const auto* input_start = &mat(row_start, col_start); |
| 1260 | const auto* input_end = &mat(slice_row_start + slice_num_rows - 1, |
| 1261 | slice_col_start + slice_num_cols - 1); |
| 1262 | const int mat_num_cols = mat.dimension(1); |
| 1263 | const int row_slice_size = slice_num_rows * mat_num_cols; |
| 1264 | |
| 1265 | const int aligned_end = slice_num_cols / N * slice_num_rows; |
| 1266 | const int e1 = std::min(e, aligned_end); |
| 1267 | while (s < e1) { |
| 1268 | CopyAndMayBeInterleave<TR>(out_start, input_start, N); |
| 1269 | out_start += N; |
| 1270 | input_start += mat_num_cols; |
| 1271 | if (input_start > input_end) { |
| 1272 | input_start = input_start - row_slice_size + N; |
| 1273 | } |
| 1274 | ++s; |
| 1275 | } |
| 1276 | int s1 = std::max(s, aligned_end); |
| 1277 | const int copy_num_cols = slice_num_cols % N; |
| 1278 | while (s1 < e) { |
| 1279 | CopyAndMayBeInterleave<TR>(out_start, input_start, copy_num_cols); |
| 1280 | out_start += N; |
| 1281 | input_start += mat_num_cols; |
| 1282 | ++s1; |
| 1283 | } |
| 1284 | if (counter) counter->DecrementCount(); |
| 1285 | }; |
| 1286 | |
| 1287 | int start = 0; |
| 1288 | int end = 0; |
| 1289 | int num_out_rows = (slice_num_cols + N - 1) / N * slice_num_rows; |
| 1290 | DCHECK_LE(num_out_rows, buffer->dimension(0)); |
| 1291 | for (int i = std::max(1, num_threads); i > 0; --i) { |
| 1292 | end = start + num_out_rows / i; |
| 1293 | thread_pool->workers->Schedule([=]() { shuffle_work(start, end); }); |
| 1294 | num_out_rows -= (end - start); |
| 1295 | start = end; |
| 1296 | } |
| 1297 | return counter; |
| 1298 | } |
| 1299 | |
| 1300 | template <typename TL, typename TR> |
| 1301 | inline void SparseMatMul<TL, TR>::SliceMatrix( |
nothing calls this directly
no test coverage detected