1 #include "caffe2/operators/tile_op.h" 8 bool TileOp<CPUContext>::RunOnDevice() {
10 TensorTypes<std::int32_t, std::int64_t, float, double, std::string>>::
16 bool TileOp<CPUContext>::DoRunWithType<std::string>() {
17 if (InputSize() > 1) {
24 Input(1).dim() == 1 && Input(1).numel() == 1,
25 "Input `tiles` should be a vector of size 1.");
26 tiles_ = GetArgFromTensor(Input(1));
32 if (Input(1).IsType<std::int64_t>()) {
36 if (InputSize() > 2) {
38 Input(2).dim() == 1 && Input(2).numel() == 1,
39 "Input `axis` should be a vector of size 1.");
40 axis_ = GetArgFromTensor(Input(2));
44 "Argument `axis` is missing and was not specified as input.");
49 "Argument `tiles` is missing and was not specified as input.");
52 "Argument `axis` is missing and was not specified as input.");
55 const auto& X = Input(0);
57 const int axis = X.canonical_axis_index(axis_);
60 std::vector<std::int64_t> Y_dims = X.sizes().vec();
61 Y_dims[axis] *= tiles_;
65 const int outer_size = X.size_to_dim(axis);
67 const int inner_size = X.size_from_dim(axis);
69 const TypeMeta& meta = X.dtype();
70 const int item_size = X.itemsize();
71 const char* X_ptr =
reinterpret_cast<const char*
>(X.raw_data());
72 char* Y_ptr =
reinterpret_cast<char*
>(Y->raw_mutable_data(meta));
73 for (
int i = 0; i < outer_size; ++i) {
74 for (
int t = 0; t < tiles_; ++t) {
75 context_.CopyItemsSameDevice(meta, inner_size, X_ptr, Y_ptr);
76 Y_ptr += inner_size * item_size;
78 X_ptr += inner_size * item_size;
83 REGISTER_CPU_OPERATOR(Tile, TileOp<CPUContext>);
84 REGISTER_CPU_OPERATOR(TileGradient, TileGradientOp<CPUContext>);
89 .TensorInferenceFunction([](
const OperatorDef& def,
90 const std::vector<TensorShape>& in) {
91 std::vector<TensorShape> out(1);
92 out[0] = TensorShape(in[0]);
93 ArgumentHelper helper(def);
94 const std::int32_t tiles =
95 helper.GetSingleArgument<std::int32_t>(
"tiles", 1);
96 const std::int32_t axis =
97 helper.GetSingleArgument<std::int32_t>(
"axis", 0);
101 out[0].set_unknown_shape(
true);
103 const auto canonical_axis =
104 canonical_axis_index_(axis, out[0].dims().size());
106 canonical_axis, out[0].dims().Get(canonical_axis) * tiles);
111 Constructs a tensor by tiling a given tensor along a specified axis. This operation creates a new tensor by replicating the input tensor a number of times specified by the `tiles` argument along the `axis` dimension. The output tensor's `axis` dimension has $(X.dims(axis) * tiles)$ elements. 114 - https://github.com/pytorch/pytorch/blob/master/caffe2/operators/tile_op.cc 118 <summary> <b>Example</b> </summary> 124 workspace.ResetWorkspace() 126 op = core.CreateOperator( 128 ["X", "tiles", "axis"], 132 workspace.FeedBlob("X", np.random.randint(10, size=(5,5))) 133 workspace.FeedBlob("tiles", np.array([5]).astype(np.int32)) 134 workspace.FeedBlob("axis", np.array([1]).astype(np.int32)) 135 print("X:", workspace.FetchBlob("X")) 136 workspace.RunOperatorOnce(op) 137 print("Y:", workspace.FetchBlob("Y")) 152 [[9 1 7 1 3 9 1 7 1 3 9 1 7 1 3 9 1 7 1 3 9 1 7 1 3] 153 [2 3 6 2 5 2 3 6 2 5 2 3 6 2 5 2 3 6 2 5 2 3 6 2 5] 154 [0 9 2 6 4 0 9 2 6 4 0 9 2 6 4 0 9 2 6 4 0 9 2 6 4] 155 [5 8 1 5 9 5 8 1 5 9 5 8 1 5 9 5 8 1 5 9 5 8 1 5 9] 156 [2 0 1 3 7 2 0 1 3 7 2 0 1 3 7 2 0 1 3 7 2 0 1 3 7]] 163 .Arg("tiles",
"(*int*): number of replicas")
164 .Arg(
"axis",
"(*int*): axis to replicate along")
165 .Input(0,
"X",
"(*Tensor*): input tensor")
169 "(*Tensor`<int>`*): [OPTIONAL] number of replicas (overrides `tiles` argument)")
173 "(*Tensor`<int>`*): [OPTIONAL] axis to replicate along (overrides `axis` argument)")
174 .Output(0,
"Y",
"(*Tensor*): output tensor")
175 .InheritOnnxSchema();
177 OPERATOR_SCHEMA(TileGradient).NumInputs(1, 3).NumOutputs(1);
181 class GetTileGradient :
public GradientMakerBase {
182 using GradientMakerBase::GradientMakerBase;
183 std::vector<OperatorDef> GetGradientDefs()
override {
186 std::vector<std::string> g_inputs({GO(0)});
187 if (Def().input_size() > 1) {
188 g_inputs.push_back(I(1));
190 if (Def().input_size() > 2) {
191 g_inputs.push_back(I(2));
193 return SingleGradientDef(
194 "TileGradient",
"", g_inputs, std::vector<std::string>{GI(0)});
200 REGISTER_GRADIENT(Tile, GetTileGradient);
A global dictionary that holds information about what Caffe2 modules have been loaded in the current ...
bool HasArgument(const string &name) const
Checks if the operator has an argument of the given name.