Skip to content

Commit 454dfc3

Browse files
smessmerRob Kunkle
authored and
Rob Kunkle
committed
Implement calling of c10 ops from c2 (pytorch#9369)
Summary: Pull Request resolved: pytorch#9369 This adds the capability for caffe2 to call c10 operators and adds a dummy c10 sigmoid op as a proof of concept. I used this test script to make sure it works: from caffe2.python import workspace, model_helper import numpy as np data1 = np.random.rand(16, 100).astype(np.float32) workspace.FeedBlob("data1", data1) m = model_helper.ModelHelper(name="my net") sigmoid1 = m.net.C10Sigmoid_DontUseThisOpYet("data1", "sigmoid1") sigmoid2 = m.net.Sigmoid("data1", "sigmoid2") workspace.RunNetOnce(m.param_init_net) workspace.CreateNet(m.net) data1 = np.random.rand(16, 100).astype(np.float32) workspace.FeedBlob("data1", data1) workspace.RunNet(m.name, 1) print(workspace.FetchBlob("data1")) print(workspace.FetchBlob("sigmoid1")) print(workspace.FetchBlob("sigmoid2")) (and check that both sigmoid outputs are the same) Reviewed By: ezyang Differential Revision: D8814669 fbshipit-source-id: eeb0e7a854727f1617a3c592a662a7e5ae226f40
1 parent 9ff0063 commit 454dfc3

File tree

7 files changed

+394
-242
lines changed

7 files changed

+394
-242
lines changed

caffe2/core/operator.cc

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
#include "caffe2/utils/proto_utils.h"
1515
#include "caffe2/utils/string_utils.h"
1616

17+
#include "caffe2/core/operator_c10wrapper.h"
18+
1719
CAFFE2_DEFINE_int(
1820
caffe2_operator_max_engine_name_length,
1921
10,
@@ -75,8 +77,10 @@ GlobalEnginePrefType& g_global_engine_pref() {
7577
return *g_global_engine_pref_;
7678
}
7779

78-
unique_ptr<OperatorBase> TryCreateOperator(
79-
const string& key, const OperatorDef& operator_def, Workspace* ws) {
80+
unique_ptr<OperatorBase> TryCreateC2Operator(
81+
const string& key,
82+
const OperatorDef& operator_def,
83+
Workspace* ws) {
8084
const auto& type = operator_def.device_option().device_type();
8185
CAFFE_ENFORCE(
8286
gDeviceTypeRegistry()->count(type),
@@ -96,6 +100,24 @@ unique_ptr<OperatorBase> TryCreateOperator(
96100
}
97101
}
98102

103+
unique_ptr<OperatorBase> TryCreateC10Operator(
104+
const string& key,
105+
const OperatorDef& operator_def,
106+
Workspace* ws) {
107+
return C10OperatorRegistry()->Create(key, operator_def, ws);
108+
}
109+
110+
unique_ptr<OperatorBase> TryCreateOperator(
111+
const string& key,
112+
const OperatorDef& operator_def,
113+
Workspace* ws) {
114+
if (auto op = TryCreateC10Operator(key, operator_def, ws)) {
115+
return op;
116+
} else {
117+
return TryCreateC2Operator(key, operator_def, ws);
118+
}
119+
}
120+
99121
unique_ptr<OperatorBase> _CreateOperator(
100122
const OperatorDef& operator_def,
101123
Workspace* ws) {
@@ -656,11 +678,17 @@ std::set<std::string> GetRegisteredOperators() {
656678
for (const auto& name : CUDAOperatorRegistry()->Keys()) {
657679
all_keys.emplace(name);
658680
}
681+
659682
// HIP operators
660683
for (const auto& name : HIPOperatorRegistry()->Keys()) {
661684
all_keys.emplace(name);
662685
}
663686

687+
// C10 operators
688+
for (const auto& name : C10OperatorRegistry()->Keys()) {
689+
all_keys.emplace(name);
690+
}
691+
664692
return all_keys;
665693
}
666694

caffe2/core/operator_c10wrapper.cc

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#include "caffe2/core/operator_c10wrapper.h"
2+
3+
namespace caffe2 {
4+
5+
CAFFE_DEFINE_REGISTRY(
6+
C10OperatorRegistry,
7+
OperatorBase,
8+
const OperatorDef&,
9+
Workspace*);
10+
}

caffe2/core/operator_c10wrapper.h

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
#pragma once
2+
3+
#include "caffe2/core/dispatch/Dispatcher.h"
4+
#include "caffe2/core/operator.h"
5+
6+
namespace caffe2 {
7+
8+
/**
9+
* To make a c10 operator "C10Add" callable from caffe2 as "C2MyAddOpName", just
10+
* write
11+
*
12+
* REGISTER_C10_OPERATOR_FOR_CAFFE2_DISPATCH(C10Add, C2MyAddOpName)
13+
*
14+
* Note: This wrapper currently only supports C10 ops that have exactly one
15+
* output and take that in the last parameter as "Tensor* output".
16+
* TODO: Figure out a better way to handle output parameters
17+
*/
18+
19+
template <class OpSchemaDef, class Context>
20+
class C10OperatorWrapper final : public Operator<Context> {
21+
using Schema = c10::OpSchema<OpSchemaDef>;
22+
23+
public:
24+
C10OperatorWrapper(const OperatorDef& operator_def, Workspace* ws)
25+
: Operator<Context>(operator_def, ws) {}
26+
27+
USE_OPERATOR_CONTEXT_FUNCTIONS;
28+
29+
bool RunOnDevice() override {
30+
RunOnDevice_(
31+
c10::guts::make_index_sequence<Schema::signature::num_args - 1>());
32+
return true;
33+
}
34+
35+
private:
36+
template <size_t... InputIndex>
37+
void RunOnDevice_(c10::guts::index_sequence<InputIndex...>) {
38+
c10::Dispatcher<OpSchemaDef>::call(Input(InputIndex)..., Output(0));
39+
}
40+
};
41+
42+
CAFFE_DECLARE_REGISTRY(
43+
C10OperatorRegistry,
44+
OperatorBase,
45+
const OperatorDef&,
46+
Workspace*);
47+
48+
// TODO Currently we only register the CPU variant. This is going to be fixed
49+
// once the tensor detemplatization lands.
50+
#define REGISTER_C10_OPERATOR_FOR_CAFFE2_DISPATCH(OpSchemaDef, Name) \
51+
CAFFE_REGISTER_CLASS( \
52+
C10OperatorRegistry, Name, C10OperatorWrapper<OpSchemaDef, CPUContext>)
53+
54+
} // namespace caffe2

caffe2/operators/c10_sigmoid_op.cc

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#include "c10_sigmoid_op.h"
2+
#include "caffe2/core/dispatch/OpSchemaRegistration.h"
3+
#include "caffe2/core/operator_c10wrapper.h"
4+
5+
using caffe2::CPUContext;
6+
using caffe2::Tensor;
7+
8+
C10_DEFINE_OP_SCHEMA(caffe2::SigmoidOp);
9+
10+
namespace caffe2 {
11+
REGISTER_C10_OPERATOR_FOR_CAFFE2_DISPATCH(
12+
SigmoidOp,
13+
C10Sigmoid_DontUseThisOpYet)
14+
}

caffe2/operators/c10_sigmoid_op.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#pragma once
2+
3+
#include "caffe2/core/tensor.h"
4+
#include "caffe2/utils/Array.h"
5+
6+
namespace caffe2 {
7+
8+
struct SigmoidOp final {
9+
static constexpr const char* name = "sigmoid";
10+
11+
using Signature = void(const Tensor& input, Tensor* output);
12+
13+
static constexpr c10::guts::array<const char*, 2> parameter_names = {
14+
{"input", "output"}};
15+
};
16+
17+
} // namespace caffe2
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#include "c10_sigmoid_op.h"
2+
#include "caffe2/core/dispatch/KernelRegistration.h"
3+
#include "caffe2/utils/eigen_utils.h"
4+
#include "caffe2/utils/math.h"
5+
6+
using caffe2::CPUContext;
7+
using caffe2::Tensor;
8+
9+
namespace {
10+
template <class DataType>
11+
void sigmoid_op_cpu_impl(
12+
const Tensor& input,
13+
Tensor* output) {
14+
output->ResizeLike(input);
15+
16+
caffe2::ConstEigenVectorArrayMap<DataType> xM(
17+
input.data<DataType>(), input.size());
18+
caffe2::EigenVectorArrayMap<DataType>(
19+
output->mutable_data<DataType>(), input.size()) = 1. / (1. + (-xM).exp());
20+
}
21+
} // namespace
22+
23+
namespace c10 {
24+
C10_REGISTER_KERNEL(caffe2::SigmoidOp)
25+
.kernel(&sigmoid_op_cpu_impl<float>)
26+
.dispatchKey({DeviceTypeId::CPU,
27+
LayoutId(0),
28+
caffe2::TypeMeta::Id<float>()});
29+
} // namespace c10

0 commit comments

Comments
 (0)