Skip to content

Commit

Permalink
Removing some dependency edges from Blob to other caffe2 (pytorch#11923)
Browse files Browse the repository at this point in the history
Summary:
Pull Request resolved: pytorch#11923

This is pre-work to allow moving Blob to ATen/core, which cannot depend on caffe2 anymore.
(1) Removing the Blob -> Tensor dependency allows us to move Blob to ATen/core and use it inside IValue without having to wait for the Tensor merge to be complete.
(2) In the final Blob design, we want it to be a very small class that doesn't have any special treatment for Tensor (or to be more correct, doesn't allow storing Tensor anymore), so this is anyhow the direction we want to go.

This changes call sites that will have to be moved to IValue later, but they cannot be moved to IValue directly, because for that, IValue first needs to be able to store Blob, which in turn first needs this diff and some other changes coming up in future diffs.

Codemods:
$ codemod --extensions h,hpp,c,cpp,cc "([a-zA-Z0-9_]+)\\.IsTensorType\\(" "BlobIsTensorType(\\1, "
$ codemod --extensions h,hpp,c,cpp,cc "([a-zA-Z0-9_]+)->IsTensorType\\(" "BlobIsTensorType(*\\1, "
$ codemod --extensions h,hpp,c,cpp,cc "([a-zA-Z0-9_]+)\\.GetMutableTensor\\(" "BlobGetMutableTensor(\\1, "
$ codemod --extensions h,hpp,c,cpp,cc "([a-zA-Z0-9_]+)->GetMutableTensor\\(" "BlobGetMutableTensor(*\\1, "

It is, however, not only these codemods because regex based refactoring was only able to match a small amount of the call sites. To catch more, I wouldn've needed a AST aware tool like clangr, which I didn't figure out how to use.

Reviewed By: ezyang

Differential Revision: D9979976

fbshipit-source-id: 2ea17724e223b5b73b44f99362727759ca689e61
  • Loading branch information
smessmer authored and facebook-github-bot committed Sep 25, 2018
1 parent dfa03e9 commit 17a65bf
Show file tree
Hide file tree
Showing 66 changed files with 380 additions and 371 deletions.
6 changes: 3 additions & 3 deletions binaries/benchmark_helper.cc
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ void loadInput(
CAFFE_THROW("Not support GPU on mobile.");
#endif
} else {
caffe2::TensorCPU* tensor = blob->GetMutableTensor(caffe2::CPU);
caffe2::TensorCPU* tensor = BlobGetMutableTensor(blob, caffe2::CPU);
CHECK_NOTNULL(tensor);
tensor->Resize(input_dims);
if (input_type_list[i] == "uint8_t") {
Expand Down Expand Up @@ -200,7 +200,7 @@ void fillInputBlob(
int protos_size = tensor_kv.second.protos_size();
caffe2::TensorProto* tensor_proto =
tensor_kv.second.mutable_protos(iteration % protos_size);
caffe2::TensorCPU* tensor = blob->GetMutableTensor(caffe2::CPU);
caffe2::TensorCPU* tensor = BlobGetMutableTensor(blob, caffe2::CPU);
if (tensor_proto->data_type() == caffe2::TensorProto::STRING) {
int total_size = tensor_proto->string_data_size();
for (size_t i = 0; i < total_size; i++) {
Expand Down Expand Up @@ -298,7 +298,7 @@ void writeOutput(
#endif
} else {
writeTextOutput<caffe2::CPUContext, caffe2::TensorCPU>(
workspace->GetBlob(name)->GetMutableTensor(caffe2::CPU),
BlobGetMutableTensor(workspace->GetBlob(name), caffe2::CPU),
output_prefix,
name);
}
Expand Down
2 changes: 1 addition & 1 deletion binaries/speed_benchmark.cc
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ int main(int argc, char** argv) {
if (blob == nullptr) {
blob = workspace->CreateBlob(input_names[i]);
}
caffe2::TensorCPU* tensor = blob->GetMutableTensor(caffe2::CPU);
caffe2::TensorCPU* tensor = BlobGetMutableTensor(blob, caffe2::CPU);
CHECK_NOTNULL(tensor);
tensor->Resize(input_dims);
if (input_type_list[i] == "uint8_t") {
Expand Down
2 changes: 1 addition & 1 deletion caffe2/contrib/gloo/common.cc
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ namespace caffe2 {
namespace gloo {

void signalFailure(Blob* status_blob, std::exception& /* unused */) {
auto* res = status_blob->GetMutableTensor(CPU);
auto* res = BlobGetMutableTensor(status_blob, CPU);
res->Resize(1);
res->template mutable_data<int32_t>()[0] = 1;
}
Expand Down
2 changes: 1 addition & 1 deletion caffe2/contrib/nervana/nervana_fc_op_gpu_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ static void AddConstInput(const std::vector<int>& shape, const float value,
option.set_device_type(PROTO_CUDA);
CUDAContext context(option);
Blob* blob = ws->CreateBlob(name);
auto* tensor = blob->GetMutableTensor(CUDA);
auto* tensor = BlobGetMutableTensor(blob, CUDA);
tensor->Resize(shape);
math::Set<float, CUDAContext>(tensor->size(), value,
tensor->mutable_data<float>(),
Expand Down
4 changes: 2 additions & 2 deletions caffe2/contrib/tensorrt/tensorrt_tranformer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -95,10 +95,10 @@ void BlobToTensorProto(
}

// Set values
if (blob->IsTensorType(CPU)) {
if (BlobIsTensorType(*blob, CPU)) {
const auto& cpu_tensor = blob->template Get<TensorCPU>();
CPUTensorToTensorProto(cpu_tensor, t);
} else if (blob->IsTensorType(CUDA)) {
} else if (BlobIsTensorType(*blob, CUDA)) {
const auto& cuda_tensor = blob->template Get<TensorCUDA>();
const auto cpu_tensor = TensorCPU(cuda_tensor, context);
context->FinishDeviceComputation();
Expand Down
54 changes: 28 additions & 26 deletions caffe2/core/blob.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,16 @@
#include <typeinfo>
#include <type_traits>
#include <vector>

#include "caffe2/core/blob_serializer_base.h"
#include "caffe2/core/common.h"

#include <ATen/core/typeid.h>
#include "caffe2/core/logging.h"
#include "caffe2/core/tensor.h"
#include "caffe2/core/typeid.h"
#include "caffe2/proto/caffe2_pb.h"

namespace caffe2 {

class Tensor;

/**
* @brief Blob is a general container that hosts a typed pointer.
*
Expand Down Expand Up @@ -50,15 +50,6 @@ class CAFFE2_API Blob final {
return meta_.Match<T>();
}

bool IsTensorType(DeviceType device_type) const {
bool is_match = meta_.Match<Tensor>();
auto* tensor = static_cast<Tensor*>(pointer_);
if (is_match && tensor && tensor->GetDeviceType() == device_type) {
return true;
}
return false;
}

/**
* Returns the meta info of the blob.
*/
Expand Down Expand Up @@ -109,9 +100,6 @@ class CAFFE2_API Blob final {
std::is_default_constructible<T>::value,
"GetMutable can't be called with non-default-constructible types. "
"Try using specialized methods");
static_assert(
!std::is_same<T, Tensor>::value,
"Use GetMutableTensor(DeviceType) instead");
if (IsType<T>()) {
return static_cast<T*>(pointer_);
} else {
Expand All @@ -129,16 +117,6 @@ class CAFFE2_API Blob final {
}
}

inline Tensor* GetMutableTensor(DeviceType device_type) {
if (IsTensorType(device_type)) {
return static_cast<Tensor*>(pointer_);
} else {
VLOG(1) << "Create new mutable object " << TypeMeta::TypeName<Tensor>()
<< " DeviceType:" << device_type;
return Reset<Tensor>(new Tensor(device_type));
}
}

/**
* Sets the underlying object to the allocated one. The Blob then takes over
* the ownership of the passed in pointer. If there is already an object in
Expand Down Expand Up @@ -248,5 +226,29 @@ inline void swap(Blob& lhs, Blob& rhs) {
lhs.swap(rhs);
}

inline bool BlobIsTensorType(const Blob& blob, DeviceType device_type) {
bool is_match = blob.meta().Match<Tensor>();
if (!is_match) {
return false;
}
const Tensor* tensor = &blob.Get<Tensor>();
return tensor && tensor->GetDeviceType() == device_type;
}

inline Tensor* BlobGetMutableTensor(Blob* blob, DeviceType device_type) {
if (blob->IsType<Tensor>()) {
Tensor* tensor = blob->GetMutable<Tensor>();
if (tensor->GetDeviceType() == device_type) {
return tensor;
}
}

// if we're here, then either Blob didn't hold a Tensor
// or that Tensor had the wrong DeviceType.
VLOG(1) << "Create new mutable object " << TypeMeta::TypeName<Tensor>()
<< " DeviceType:" << device_type;
return blob->Reset<Tensor>(new Tensor(device_type));
}

} // namespace caffe2
#endif // CAFFE2_CORE_BLOB_H_
8 changes: 4 additions & 4 deletions caffe2/core/blob_gpu_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ TYPED_TEST(TensorGPUDeathTest, CannotAccessDataWhenEmpty) {
for (int i = 0; i < 6; ++i) { \
cpu_tensor.mutable_data<TypeParam>()[i] = static_cast<TypeParam>(i); \
} \
blob.GetMutableTensor(CUDA)->CopyFrom(cpu_tensor); \
BlobGetMutableTensor(&blob, CUDA)->CopyFrom(cpu_tensor); \
string serialized = SerializeBlob(blob, "test"); \
BlobProto proto; \
CAFFE_ENFORCE(proto.ParseFromString(serialized)); \
Expand All @@ -149,7 +149,7 @@ TYPED_TEST(TensorGPUDeathTest, CannotAccessDataWhenEmpty) {
} \
Blob new_blob; \
EXPECT_NO_THROW(DeserializeBlob(serialized, &new_blob)); \
EXPECT_TRUE(new_blob.IsTensorType(CUDA)); \
EXPECT_TRUE(BlobIsTensorType(new_blob, CUDA)); \
Tensor new_cpu_tensor(blob.Get<Tensor>(), CPU); \
EXPECT_EQ(new_cpu_tensor.ndim(), 2); \
EXPECT_EQ(new_cpu_tensor.dim(0), 2); \
Expand Down Expand Up @@ -199,15 +199,15 @@ TEST(TensorTest, TensorSerializationMultiDevices) {
// Test if the restored blob is still of the same device.
blob.Reset();
EXPECT_NO_THROW(DeserializeBlob(serialized, &blob));
EXPECT_TRUE(blob.IsTensorType(CUDA));
EXPECT_TRUE(BlobIsTensorType(blob, CUDA));
EXPECT_EQ(GetGPUIDForPointer(blob.Get<TensorCUDA>().data<float>()),
gpu_id);
// Test if we force the restored blob on a different device, we
// can still get so.
blob.Reset();
proto.mutable_tensor()->mutable_device_detail()->set_cuda_gpu_id(0);
EXPECT_NO_THROW(DeserializeBlob(proto.SerializeAsString(), &blob));
EXPECT_TRUE(blob.IsTensorType(CUDA));
EXPECT_TRUE(BlobIsTensorType(blob, CUDA));
EXPECT_EQ(GetGPUIDForPointer(blob.Get<TensorCUDA>().data<float>()), 0);
}
}
Expand Down
3 changes: 2 additions & 1 deletion caffe2/core/blob_serialization.cc
Original file line number Diff line number Diff line change
Expand Up @@ -363,7 +363,8 @@ void TensorDeserializer::Deserialize(const BlobProto& blob_proto, Blob* blob) {
auto tensor_proto = blob_proto.tensor();
Deserialize(
tensor_proto,
blob->GetMutableTensor(
BlobGetMutableTensor(
blob,
static_cast<DeviceType>(tensor_proto.device_detail().device_type())));
}

Expand Down
30 changes: 15 additions & 15 deletions caffe2/core/blob_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -86,15 +86,15 @@ TEST(BlobTest, Blob) {
int* int_unused CAFFE2_UNUSED = blob.GetMutable<int>();
EXPECT_TRUE(blob.IsType<int>());
EXPECT_FALSE(blob.IsType<BlobTestFoo>());
EXPECT_FALSE(blob.IsTensorType(CPU));
EXPECT_FALSE(BlobIsTensorType(blob, CPU));

BlobTestFoo* foo_unused CAFFE2_UNUSED = blob.GetMutable<BlobTestFoo>();
EXPECT_TRUE(blob.IsType<BlobTestFoo>());
EXPECT_FALSE(blob.IsType<int>());
EXPECT_FALSE(blob.IsTensorType(CPU));
EXPECT_FALSE(BlobIsTensorType(blob, CPU));

Tensor* tensor_unused CAFFE2_UNUSED = blob.GetMutableTensor(CPU);
EXPECT_TRUE(blob.IsTensorType(CPU));
Tensor* tensor_unused CAFFE2_UNUSED = BlobGetMutableTensor(&blob, CPU);
EXPECT_TRUE(BlobIsTensorType(blob, CPU));
EXPECT_FALSE(blob.IsType<BlobTestFoo>());
EXPECT_FALSE(blob.IsType<int>());
}
Expand Down Expand Up @@ -600,7 +600,7 @@ TEST(TensorDeathTest, CannotCastDownLargeDims) {
#define TEST_SERIALIZATION_WITH_TYPE(TypeParam, field_name) \
TEST(TensorTest, TensorSerialization_##TypeParam) { \
Blob blob; \
Tensor* tensor = blob.GetMutableTensor(CPU); \
Tensor* tensor = BlobGetMutableTensor(&blob, CPU); \
tensor->Resize(2, 3); \
for (int i = 0; i < 6; ++i) { \
tensor->mutable_data<TypeParam>()[i] = static_cast<TypeParam>(i); \
Expand All @@ -621,7 +621,7 @@ TEST(TensorDeathTest, CannotCastDownLargeDims) {
} \
Blob new_blob; \
EXPECT_NO_THROW(DeserializeBlob(serialized, &new_blob)); \
EXPECT_TRUE(new_blob.IsTensorType(CPU)); \
EXPECT_TRUE(BlobIsTensorType(new_blob, CPU)); \
const TensorCPU& new_tensor = blob.Get<TensorCPU>(); \
EXPECT_EQ(new_tensor.ndim(), 2); \
EXPECT_EQ(new_tensor.dim(0), 2); \
Expand All @@ -634,7 +634,7 @@ TEST(TensorDeathTest, CannotCastDownLargeDims) {
\
TEST(EmptyTensorTest, TensorSerialization_##TypeParam) { \
Blob blob; \
TensorCPU* tensor = blob.GetMutableTensor(CPU); \
TensorCPU* tensor = BlobGetMutableTensor(&blob, CPU); \
tensor->Resize(0, 3); \
tensor->mutable_data<TypeParam>(); \
string serialized = SerializeBlob(blob, "test"); \
Expand All @@ -650,7 +650,7 @@ TEST(TensorDeathTest, CannotCastDownLargeDims) {
EXPECT_EQ(tensor_proto.field_name##_size(), 0); \
Blob new_blob; \
EXPECT_NO_THROW(DeserializeBlob(serialized, &new_blob)); \
EXPECT_TRUE(new_blob.IsTensorType(CPU)); \
EXPECT_TRUE(BlobIsTensorType(new_blob, CPU)); \
const TensorCPU& new_tensor = blob.Get<TensorCPU>(); \
EXPECT_EQ(new_tensor.ndim(), 2); \
EXPECT_EQ(new_tensor.dim(0), 0); \
Expand All @@ -669,7 +669,7 @@ TEST_SERIALIZATION_WITH_TYPE(int64_t, int64_data)

TEST(TensorTest, TensorSerialization_CustomType) {
Blob blob;
TensorCPU* tensor = blob.GetMutableTensor(CPU);
TensorCPU* tensor = BlobGetMutableTensor(&blob, CPU);
tensor->Resize(2, 3);
for (int i = 0; i < 6; ++i) {
tensor->mutable_data<BlobTestFoo>()[i].val = i;
Expand All @@ -681,7 +681,7 @@ TEST(TensorTest, TensorSerialization_CustomType) {
EXPECT_EQ(proto.type(), "Tensor");
Blob new_blob;
EXPECT_NO_THROW(DeserializeBlob(serialized, &new_blob));
EXPECT_TRUE(new_blob.IsTensorType(CPU));
EXPECT_TRUE(BlobIsTensorType(new_blob, CPU));
const TensorCPU& new_tensor = blob.Get<TensorCPU>();
EXPECT_EQ(new_tensor.ndim(), 2);
EXPECT_EQ(new_tensor.dim(0), 2);
Expand All @@ -696,7 +696,7 @@ TEST(TensorTest, TensorSerialization_CustomType) {
TEST(TensorTest, Half) {
const int64_t kSize = 3000000;
Blob blob;
TensorCPU* tensor = blob.GetMutableTensor(CPU);
TensorCPU* tensor = BlobGetMutableTensor(&blob, CPU);
tensor->Resize(kSize);
for (int i = 0; i < tensor->size(); ++i) {
tensor->mutable_data<at::Half>()[i].x = i % 10000;
Expand Down Expand Up @@ -724,7 +724,7 @@ TEST(TensorTest, Half) {
}
Blob new_blob;
EXPECT_NO_THROW(DeserializeBlob(serialized, &new_blob));
EXPECT_TRUE(new_blob.IsTensorType(CPU));
EXPECT_TRUE(BlobIsTensorType(new_blob, CPU));
const TensorCPU& new_tensor = blob.Get<TensorCPU>();
EXPECT_EQ(new_tensor.ndim(), 1);
EXPECT_EQ(new_tensor.dim(0), kSize);
Expand Down Expand Up @@ -860,7 +860,7 @@ TYPED_TEST(TypedTensorTest, BigTensorSerialization) {
{
VLOG(1) << "Test begin";
Blob blob;
Tensor* tensor = blob.GetMutableTensor(CPU);
Tensor* tensor = BlobGetMutableTensor(&blob, CPU);
VLOG(1) << "Allocating blob";
tensor->Resize(d1, d2);
auto mutableData = tensor->mutable_data<TypeParam>();
Expand Down Expand Up @@ -903,7 +903,7 @@ TYPED_TEST(TypedTensorTest, BigTensorSerialization) {
load_op->Run();
VLOG(1) << "Reading blob from workspace";
auto new_blob = ws.GetBlob("test");
EXPECT_TRUE(new_blob->IsTensorType(CPU));
EXPECT_TRUE(BlobIsTensorType(*new_blob, CPU));
const auto& new_tensor = new_blob->Get<TensorCPU>();

EXPECT_EQ(new_tensor.ndim(), d1);
Expand Down Expand Up @@ -1030,7 +1030,7 @@ TEST(CustomChunkSize, BigTensorSerialization) {
int64_t size = d1 * d2;

Blob blob;
TensorCPU* tensor = blob.GetMutableTensor(CPU);
TensorCPU* tensor = BlobGetMutableTensor(&blob, CPU);
tensor->Resize(d1, d2);
tensor->mutable_data<float>();
std::mutex mutex;
Expand Down
6 changes: 3 additions & 3 deletions caffe2/core/operator.h
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ class CAFFE2_API OperatorBase : public Observable<OperatorBase> {
static_assert(
std::is_same<T, Tensor>::value,
"Output(int, DeviceType) is only available for Tensor");
return outputs_.at(idx)->GetMutableTensor(type);
return BlobGetMutableTensor(outputs_.at(idx), type);
}

template <typename T>
Expand All @@ -149,7 +149,7 @@ class CAFFE2_API OperatorBase : public Observable<OperatorBase> {
}

inline bool InputIsTensorType(int idx, DeviceType device_type) {
return inputs_.at(idx)->IsTensorType(device_type);
return BlobIsTensorType(*inputs_.at(idx), device_type);
}

template <typename T>
Expand All @@ -162,7 +162,7 @@ class CAFFE2_API OperatorBase : public Observable<OperatorBase> {
}

inline bool OutputIsTensorType(int idx, DeviceType type) {
return outputs_.at(idx)->IsTensorType(type);
return BlobIsTensorType(*outputs_.at(idx), type);
}

inline int InputSize() const {
Expand Down
3 changes: 2 additions & 1 deletion caffe2/core/plan_executor.cc
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,8 @@ struct WorkspaceIdInjector {
"Integer overflow while calculating GLOBAL_WORKSPACE_ID blob");
int32_t global_ws_id = (seq_++) + (static_cast<int32_t>(node_id) << 16);
Blob* global_ws_id_blob = workspace->CreateLocalBlob(GLOBAL_WORKSPACE_ID);
TensorCPU* global_ws_id_tensor = global_ws_id_blob->GetMutableTensor(CPU);
TensorCPU* global_ws_id_tensor =
BlobGetMutableTensor(global_ws_id_blob, CPU);
global_ws_id_tensor->Resize();
global_ws_id_tensor->template mutable_data<int32_t>()[0] = global_ws_id;
VLOG(1) << "Adding " << GLOBAL_WORKSPACE_ID << " = " << global_ws_id;
Expand Down
2 changes: 1 addition & 1 deletion caffe2/core/workspace.h
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ class CAFFE2_API Workspace {
auto* to_blob = CreateBlob(blob);
CAFFE_ENFORCE(to_blob);
const auto& from_tensor = from_blob->template Get<Tensor>();
auto* to_tensor = to_blob->GetMutableTensor(Context::GetDeviceType());
auto* to_tensor = BlobGetMutableTensor(to_blob, Context::GetDeviceType());
to_tensor->CopyFrom(from_tensor);
}
}
Expand Down
5 changes: 3 additions & 2 deletions caffe2/ideep/operators/concat_split_op.cc
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,9 @@ class IDEEPConcatOp final : public IDEEPOperator {
if (OperatorBase::InputBlob(i).template IsType<itensor>()) {
inputs.emplace_back(Input(i));
} else {
CAFFE_ENFORCE(OperatorBase::InputBlob(i).IsTensorType(CPU),
"Expect cpu tensor if not itensor");
CAFFE_ENFORCE(
BlobIsTensorType(OperatorBase::InputBlob(i), CPU),
"Expect cpu tensor if not itensor");
auto& tensor_cpu = OperatorBase::Input<Tensor>(i, CPU);
CAFFE_ENFORCE(tensor_cpu.dims().size() == 0 ||
tensor_cpu.size_from_dim(0) == 0,
Expand Down
Loading

0 comments on commit 17a65bf

Please sign in to comment.