mirror of
https://github.com/saymrwulf/pytorch.git
synced 2026-05-14 20:57:59 +00:00
Avoid exposing defines that conflict with google logging, since this blocks external usage of libtorch in certain cases. All the 'interesting' changes should be in these two files, and the rest should just be mechanical changes via sed. c10/util/logging_is_not_google_glog.h c10/util/logging_is_google_glog.h Fixes https://github.com/pytorch/pytorch/issues/81415 cc @miladm @malfet Pull Request resolved: https://github.com/pytorch/pytorch/pull/82032 Approved by: https://github.com/soumith, https://github.com/miladm
322 lines
8.8 KiB
C++
322 lines
8.8 KiB
C++
#include <chrono> // NOLINT
|
|
#include <thread> // NOLINT
|
|
|
|
#include <gtest/gtest.h>
|
|
#include "caffe2/core/net.h"
|
|
#include "caffe2/core/operator.h"
|
|
|
|
namespace caffe2 {
|
|
|
|
// When measuring time, we relax the measured time by +- 40ms.
|
|
#ifndef _WIN32
|
|
const int kTimeThreshold = 40;
|
|
#else
|
|
// Even more so on Windows
|
|
const int kTimeThreshold = 50;
|
|
#endif
|
|
|
|
// SleepOp basically sleeps for a given number of seconds.
|
|
// We allow arbitrary inputs and at most one output so that we can
|
|
// test scaffolding of networks. If the output is 1, it will be filled with
|
|
// vector<int64_t> with two elements: start time and end time.
|
|
class SleepOp final : public Operator<CPUContext> {
|
|
public:
|
|
SleepOp(const OperatorDef& operator_def, Workspace* ws)
|
|
: Operator<CPUContext>(operator_def, ws),
|
|
ms_(OperatorBase::GetSingleArgument<int>("ms", 1000)) {
|
|
TORCH_DCHECK_GT(ms_, 0);
|
|
TORCH_DCHECK_LT(ms_, 3600 * 1000) << "Really? This long?";
|
|
}
|
|
|
|
bool RunOnDevice() override {
|
|
auto start = std::chrono::high_resolution_clock::now();
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(ms_));
|
|
auto end = std::chrono::high_resolution_clock::now();
|
|
if (OperatorBase::OutputSize()) {
|
|
vector<int64_t>* output = OperatorBase::Output<vector<int64_t>>(0);
|
|
output->resize(2);
|
|
(*output)[0] = start.time_since_epoch().count();
|
|
(*output)[1] = end.time_since_epoch().count();
|
|
}
|
|
return true;
|
|
}
|
|
|
|
private:
|
|
int ms_;
|
|
};
|
|
|
|
OPERATOR_SCHEMA(Sleep).NumInputs(0, INT_MAX).NumOutputs(0, 1);
|
|
|
|
REGISTER_CPU_OPERATOR(Sleep, SleepOp);
|
|
REGISTER_CUDA_OPERATOR(Sleep, SleepOp);
|
|
|
|
// NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays,modernize-avoid-c-arrays)
|
|
const char kSleepNetDefString[] =
|
|
" name: \"sleepnet\""
|
|
" type: \"dag\""
|
|
" num_workers: 2"
|
|
" op {"
|
|
" output: \"sleep1\""
|
|
" name: \"sleep1\""
|
|
" type: \"Sleep\""
|
|
" arg {"
|
|
" name: \"ms\""
|
|
" i: 100"
|
|
" }"
|
|
" }"
|
|
" op {"
|
|
" input: \"sleep1\""
|
|
" output: \"sleep2\""
|
|
" name: \"sleep2\""
|
|
" type: \"Sleep\""
|
|
" arg {"
|
|
" name: \"ms\""
|
|
" i: 100"
|
|
" }"
|
|
" }"
|
|
" op {"
|
|
" output: \"sleep3\""
|
|
" name: \"sleep3\""
|
|
" type: \"Sleep\""
|
|
" arg {"
|
|
" name: \"ms\""
|
|
" i: 150"
|
|
" }"
|
|
" }";
|
|
|
|
namespace {
|
|
// Run a network and get its duration in milliseconds.
|
|
int RunNetAndGetDuration(const string& net_def_str, const string& type) {
|
|
NetDef net_def;
|
|
CAFFE_ENFORCE(TextFormat::ParseFromString(net_def_str, &net_def));
|
|
net_def.set_type(type);
|
|
Workspace ws;
|
|
unique_ptr<NetBase> net(CreateNet(net_def, &ws));
|
|
CAFFE_ENFORCE(net.get() != nullptr);
|
|
// Run once to kick in potential initialization (can be slower)
|
|
CAFFE_ENFORCE(net->Run());
|
|
// Now run and time it
|
|
auto start_time = std::chrono::system_clock::now();
|
|
CAFFE_ENFORCE(net->Run());
|
|
// Inspect the time - it should be around 200 milliseconds, since sleep3 can
|
|
// run in parallel with sleep1 and sleep2.
|
|
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(
|
|
std::chrono::system_clock::now() - start_time);
|
|
int milliseconds = duration.count();
|
|
return milliseconds;
|
|
}
|
|
} // namespace
|
|
|
|
TEST(DAGNetTest, TestDAGNetTiming) {
|
|
int ms = RunNetAndGetDuration(string(kSleepNetDefString), "dag");
|
|
EXPECT_NEAR(ms, 200, kTimeThreshold);
|
|
}
|
|
|
|
// For sanity check, we also test the sequential time - it should take 0.35
|
|
// seconds instead since everything has to be sequential.
|
|
TEST(SimpleNetTest, TestSimpleNetTiming) {
|
|
int ms = RunNetAndGetDuration(string(kSleepNetDefString), "simple");
|
|
EXPECT_NEAR(ms, 350, kTimeThreshold);
|
|
}
|
|
|
|
// This network has two operators reading the same blob at the same time. This
|
|
// should not change anything and the DAG should still make sleep2 and sleep3
|
|
// run in parallel.
|
|
// NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays,modernize-avoid-c-arrays)
|
|
const char kSleepNetDefStringReadAfterRead[] =
|
|
" name: \"sleepnet\""
|
|
" type: \"dag\""
|
|
" num_workers: 2"
|
|
" op {"
|
|
" output: \"sleep1\""
|
|
" name: \"sleep1\""
|
|
" type: \"Sleep\""
|
|
" arg {"
|
|
" name: \"ms\""
|
|
" i: 100"
|
|
" }"
|
|
" }"
|
|
" op {"
|
|
" input: \"sleep1\""
|
|
" output: \"sleep2\""
|
|
" name: \"sleep2\""
|
|
" type: \"Sleep\""
|
|
" arg {"
|
|
" name: \"ms\""
|
|
" i: 100"
|
|
" }"
|
|
" }"
|
|
" op {"
|
|
" input: \"sleep1\""
|
|
" output: \"sleep3\""
|
|
" name: \"sleep3\""
|
|
" type: \"Sleep\""
|
|
" arg {"
|
|
" name: \"ms\""
|
|
" i: 150"
|
|
" }"
|
|
" }";
|
|
|
|
TEST(DAGNetTest, TestDAGNetTimingReadAfterRead) {
|
|
int ms = RunNetAndGetDuration(string(kSleepNetDefStringReadAfterRead), "dag");
|
|
EXPECT_NEAR(ms, 250, kTimeThreshold);
|
|
}
|
|
|
|
// For sanity check, we also test the sequential time - it should take 0.35
|
|
// seconds instead since everything has to be sequential.
|
|
TEST(SimpleNetTest, TestSimpleNetTimingReadAfterRead) {
|
|
int ms =
|
|
RunNetAndGetDuration(string(kSleepNetDefStringReadAfterRead), "simple");
|
|
EXPECT_NEAR(ms, 350, kTimeThreshold);
|
|
}
|
|
|
|
// This network has two operators writing out the sleep2 blob. As a result, the
|
|
// operator sleep2-again creates a write after write dependency and the whole
|
|
// process should be sequential.
|
|
// NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays,modernize-avoid-c-arrays)
|
|
const char kSleepNetDefStringWriteAfterWrite[] =
|
|
" name: \"sleepnet\""
|
|
" type: \"dag\""
|
|
" num_workers: 2"
|
|
" op {"
|
|
" output: \"sleep1\""
|
|
" name: \"sleep1\""
|
|
" type: \"Sleep\""
|
|
" arg {"
|
|
" name: \"ms\""
|
|
" i: 100"
|
|
" }"
|
|
" }"
|
|
" op {"
|
|
" input: \"sleep1\""
|
|
" output: \"sleep2\""
|
|
" name: \"sleep2\""
|
|
" type: \"Sleep\""
|
|
" arg {"
|
|
" name: \"ms\""
|
|
" i: 100"
|
|
" }"
|
|
" }"
|
|
" op {"
|
|
" output: \"sleep2\""
|
|
" name: \"sleep2-again\""
|
|
" type: \"Sleep\""
|
|
" arg {"
|
|
" name: \"ms\""
|
|
" i: 150"
|
|
" }"
|
|
" }";
|
|
|
|
TEST(DAGNetTest, TestDAGNetTimingWriteAfterWrite) {
|
|
int ms =
|
|
RunNetAndGetDuration(string(kSleepNetDefStringWriteAfterWrite), "dag");
|
|
EXPECT_NEAR(ms, 350, kTimeThreshold);
|
|
}
|
|
|
|
TEST(SimpleNetTest, TestSimpleNetTimingWriteAfterWrite) {
|
|
int ms =
|
|
RunNetAndGetDuration(string(kSleepNetDefStringWriteAfterWrite), "simple");
|
|
EXPECT_NEAR(ms, 350, kTimeThreshold);
|
|
}
|
|
|
|
// This network has an operator writing to sleep1 while another operator is
|
|
// accessing it. As a result, the operator sleep1-again creates a write after
|
|
// read dependency and the whole process should be sequential.
|
|
// NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays,modernize-avoid-c-arrays)
|
|
const char kSleepNetDefStringWriteAfterRead[] =
|
|
" name: \"sleepnet\""
|
|
" type: \"dag\""
|
|
" num_workers: 2"
|
|
" op {"
|
|
" output: \"sleep1\""
|
|
" name: \"sleep1\""
|
|
" type: \"Sleep\""
|
|
" arg {"
|
|
" name: \"ms\""
|
|
" i: 100"
|
|
" }"
|
|
" }"
|
|
" op {"
|
|
" input: \"sleep1\""
|
|
" output: \"sleep2\""
|
|
" name: \"sleep2\""
|
|
" type: \"Sleep\""
|
|
" arg {"
|
|
" name: \"ms\""
|
|
" i: 100"
|
|
" }"
|
|
" }"
|
|
" op {"
|
|
" output: \"sleep1\""
|
|
" name: \"sleep1-again\""
|
|
" type: \"Sleep\""
|
|
" arg {"
|
|
" name: \"ms\""
|
|
" i: 150"
|
|
" }"
|
|
" }";
|
|
|
|
TEST(DAGNetTest, TestDAGNetTimingWriteAfterRead) {
|
|
int ms =
|
|
RunNetAndGetDuration(string(kSleepNetDefStringWriteAfterRead), "dag");
|
|
EXPECT_NEAR(ms, 350, kTimeThreshold);
|
|
}
|
|
|
|
TEST(SimpleNetTest, TestSimpleNetTimingWriteAfterRead) {
|
|
int ms =
|
|
RunNetAndGetDuration(string(kSleepNetDefStringWriteAfterRead), "simple");
|
|
EXPECT_NEAR(ms, 350, kTimeThreshold);
|
|
}
|
|
|
|
// This network has an operator writing to sleep1 while another
|
|
// operator has a control dependency on it. As a result, the operator
|
|
// sleep1-again creates a write after read dependency and the whole
|
|
// process should be sequential.
|
|
// NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays,modernize-avoid-c-arrays)
|
|
const char kSleepNetDefStringControlDependency[] = R"DOC(
|
|
name: "sleepnet"
|
|
type: "dag"
|
|
num_workers: 2
|
|
op {
|
|
output: "sleep1"
|
|
name: "sleep1"
|
|
type: "Sleep"
|
|
arg {
|
|
name: "ms"
|
|
i: 100
|
|
}
|
|
}
|
|
op {
|
|
control_input: "sleep1"
|
|
output: "sleep2"
|
|
name: "sleep2"
|
|
type: "Sleep"
|
|
arg {
|
|
name: "ms"
|
|
i: 100
|
|
}
|
|
}
|
|
op {
|
|
output: "sleep1"
|
|
name: "sleep1-again"
|
|
type: "Sleep"
|
|
arg {
|
|
name: "ms"
|
|
i: 150
|
|
}
|
|
}
|
|
)DOC";
|
|
|
|
TEST(DAGNetTest, TestDAGNetTimingControlDependency) {
|
|
int ms =
|
|
RunNetAndGetDuration(string(kSleepNetDefStringControlDependency), "dag");
|
|
EXPECT_NEAR(ms, 350, kTimeThreshold);
|
|
}
|
|
|
|
TEST(SimpleNetTest, TestSimpleNetTimingControlDependency) {
|
|
int ms = RunNetAndGetDuration(
|
|
string(kSleepNetDefStringControlDependency), "simple");
|
|
EXPECT_NEAR(ms, 350, kTimeThreshold);
|
|
}
|
|
|
|
} // namespace caffe2
|