File: length_split_op.h

package info (click to toggle)
pytorch 1.13.1%2Bdfsg-4
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 139,252 kB
  • sloc: cpp: 1,100,274; python: 706,454; ansic: 83,052; asm: 7,618; java: 3,273; sh: 2,841; javascript: 612; makefile: 323; xml: 269; ruby: 185; yacc: 144; objc: 68; lex: 44
file content (76 lines) | stat: -rw-r--r-- 2,304 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
#ifndef CAFFE2_OPERATORS_LENGTH_SPLIT_OP_H_
#define CAFFE2_OPERATORS_LENGTH_SPLIT_OP_H_

#include "caffe2/core/common_omp.h"
#include "caffe2/core/context.h"
#include "caffe2/core/logging.h"
#include "caffe2/core/operator.h"
#include "caffe2/utils/math.h"
#include "c10/util/irange.h"

namespace caffe2 {

template <class Context>
class LengthsSplitOp final : public Operator<Context> {
 public:
  USE_OPERATOR_CONTEXT_FUNCTIONS;

  template <class... Args>
  explicit LengthsSplitOp(Args&&... args)
      : Operator<Context>(std::forward<Args>(args)...),
        n_split_(OperatorBase::GetSingleArgument<int32_t>("n_split", 0)) {
    if (InputSize() == 1) {
      // If not specified, then must have this argument
      CAFFE_ENFORCE(
          OperatorBase::HasArgument("n_split"),
          "Argument `n_split` is missing and was not specified as input.");
      CAFFE_ENFORCE(
          n_split_ > 0,
          "`n_split` must contain a positive value for defined behavior.");
    }
  }
  ~LengthsSplitOp() {}

  bool RunOnDevice() override {
    const auto& L = Input(0);
    CAFFE_ENFORCE_EQ(L.dim(), 1, "Input `LENGTHS` should be a 1D vector.");

    if (InputSize() > 1) {
      // We potentially have n_split specified as inputs as well
      CAFFE_ENFORCE(
          Input(1).dim() == 1 && Input(1).numel() == 1,
          "Input `n_split` should be a vector of size 1.");

      const auto& input1 = Input(1);
      context_.template CopyItems<Context, CPUContext>(
          input1.dtype(), 1, input1.raw_data(), &n_split_);
    }

    CAFFE_ENFORCE(
        n_split_ > 0,
        "`n_split` must contain a positive value for defined behavior.");
    const auto M = L.numel();

    auto* Y = Output(0, {M * n_split_}, at::dtype<int32_t>());

    const int32_t* Ldata = L.template data<int32_t>();
    int32_t* Ydata = Y->template mutable_data<int32_t>();

    for (const auto i : c10::irange(M)) {
      int32_t mod = Ldata[i] % n_split_;
      int32_t res =
          mod != 0 ? math::DivUp(Ldata[i], n_split_) : Ldata[i] / n_split_ + 1;
      for (const auto j : c10::irange(n_split_)) {
        Ydata[(i * n_split_) + j] = mod-- > 0 ? res : res - 1;
      }
    }
    return true;
  }

 private:
  int32_t n_split_;
};

} // namespace caffe2

#endif // CAFFE2_OPERATORS_LENGTH_SPLIT_OP_H_