coo_sort.cc 2.57 KB
Newer Older
1
2
3
4
5
6
/*!
 *  Copyright (c) 2020 by Contributors
 * \file array/cpu/coo_sort.cc
 * \brief COO sorting
 */
#include <dgl/array.h>
7
8
9
#ifdef PARALLEL_ALGORITHMS
#include <parallel/algorithm>
#endif
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <numeric>
#include <algorithm>
#include <vector>

namespace dgl {
namespace aten {
namespace impl {

template <DLDeviceType XPU, typename IdType>
COOMatrix COOSort(COOMatrix coo, bool sort_column) {
  const int64_t nnz = coo.row->shape[0];
  const IdType* coo_row_data = static_cast<IdType*>(coo.row->data);
  const IdType* coo_col_data = static_cast<IdType*>(coo.col->data);

  // Argsort
  IdArray new_row = IdArray::Empty({nnz}, coo.row->dtype, coo.row->ctx);
  IdArray new_col = IdArray::Empty({nnz}, coo.col->dtype, coo.col->ctx);
27
  IdArray new_idx = IdArray::Empty({nnz}, coo.row->dtype, coo.row->ctx);
28
29
  IdType* new_row_data = static_cast<IdType*>(new_row->data);
  IdType* new_col_data = static_cast<IdType*>(new_col->data);
30
31
  IdType* new_idx_data = static_cast<IdType*>(new_idx->data);
  std::iota(new_idx_data, new_idx_data + nnz, 0);
32
  if (sort_column) {
33
34
35
#ifdef PARALLEL_ALGORITHMS
    __gnu_parallel::sort(
#else
36
    std::sort(
37
38
39
40
#endif
        new_idx_data,
        new_idx_data + nnz,
        [coo_row_data, coo_col_data](const IdType a, const IdType b) {
41
42
43
44
45
          return (coo_row_data[a] != coo_row_data[b]) ?
            (coo_row_data[a] < coo_row_data[b]) :
            (coo_col_data[a] < coo_col_data[b]);
        });
  } else {
46
47
48
#ifdef PARALLEL_ALGORITHMS
    __gnu_parallel::sort(
#else
49
    std::sort(
50
51
52
53
54
#endif
        new_idx_data,
        new_idx_data + nnz,
        [coo_row_data](const IdType a, const IdType b) {
          return coo_row_data[a] < coo_row_data[b];
55
56
57
58
        });
  }

  // Reorder according to shuffle
59
#pragma omp parallel for
60
  for (IdType i = 0; i < nnz; ++i) {
61
62
63
64
65
66
67
68
69
70
71
72
73
74
    new_row_data[i] = coo_row_data[new_idx_data[i]];
    new_col_data[i] = coo_col_data[new_idx_data[i]];
  }

  if (COOHasData(coo)) {
    const IdType* coo_data_data = static_cast<IdType*>(coo.data->data);
    IdArray new_data = IdArray::Empty({nnz}, coo.row->dtype, coo.row->ctx);
    IdType* new_data_data = static_cast<IdType*>(new_data->data);
#pragma omp parallel for
    for (IdType i = 0; i < nnz; ++i) {
      new_data_data[i] = coo_data_data[new_idx_data[i]];
    }

    new_idx = new_data;
75
76
77
78
  }

  return COOMatrix{
      coo.num_rows, coo.num_cols, std::move(new_row), std::move(new_col),
79
      std::move(new_idx), true, sort_column};
80
81
82
83
84
85
86
87
}

template COOMatrix COOSort<kDLCPU, int32_t>(COOMatrix, bool);
template COOMatrix COOSort<kDLCPU, int64_t>(COOMatrix, bool);

}  // namespace impl
}  // namespace aten
}  // namespace dgl