blob: 5d65cdc6739c20c8ba36150966ab02daa5ae8a17 [file] [log] [blame]
#pragma once
#include "caffe2/core/blob_serialization.h"
#include "caffe2/core/context.h"
#include "caffe2/core/operator.h"
#include "caffe2/core/timer.h"
#include <mutex>
namespace caffe2 {
struct QPSMetricState {
Timer lifetimeTimer;
Timer windowTimer;
int64_t windowExamples{0};
int64_t lifetimeExamples{0};
std::mutex mutex;
};
CAFFE_KNOWN_TYPE(std::unique_ptr<QPSMetricState>);
class QPSMetricStateSerializer : public BlobSerializerBase {
public:
/**
* Serializes a std::unique_ptr<QPSMetricState>. Note that this blob has to
* contain std::unique_ptr<QPSMetricState>, otherwise this function produces a
* fatal error.
*/
void Serialize(
const Blob& blob,
const string& name,
BlobSerializerBase::SerializationAcceptor acceptor) override;
};
class QPSMetricStateDeserializer : public BlobDeserializerBase {
public:
void Deserialize(const BlobProto& proto, Blob* blob) override;
};
// TODO(amalevich): Consider making all the code below templated, so it'll be
// easier to share it across different metrics.
class CreateQPSMetricOp final : public Operator<CPUContext> {
public:
using Operator<CPUContext>::Operator;
bool RunOnDevice() override {
*OperatorBase::Output<std::unique_ptr<QPSMetricState>>(0) =
caffe2::make_unique<QPSMetricState>();
return true;
}
};
class QPSMetricOp final : public Operator<CPUContext> {
public:
using Operator<CPUContext>::Operator;
bool RunOnDevice() override {
auto& metricsBlob =
*OperatorBase::Input<std::unique_ptr<QPSMetricState>>(0);
auto examples = Input(1).dim(0);
// All changes to metrics should happen under critical section.
{
std::lock_guard<std::mutex> guard(metricsBlob.mutex);
metricsBlob.windowExamples += examples;
metricsBlob.lifetimeExamples += examples;
}
return true;
}
};
class QPSMetricReportOp final : public Operator<CPUContext> {
public:
using Operator<CPUContext>::Operator;
bool RunOnDevice() override {
auto& metricsBlob =
*OperatorBase::Input<std::unique_ptr<QPSMetricState>>(0);
// All changes to metrics should happen under critical section.
float windowSeconds = -1;
int64_t windowExamples = 0;
float lifetimeSeconds = -1;
int64_t lifetimeExamples = 0;
{
std::lock_guard<std::mutex> guard(metricsBlob.mutex);
windowSeconds = metricsBlob.windowTimer.Seconds();
lifetimeSeconds = metricsBlob.lifetimeTimer.Seconds();
windowExamples = metricsBlob.windowExamples;
lifetimeExamples = metricsBlob.lifetimeExamples;
metricsBlob.windowTimer.Start();
metricsBlob.windowExamples = 0;
}
// TODO(amalevich): Add output blobs, so it would be relatively easy to
// access this metrics from the outside
LOG(INFO) << "Lifetime Examples = " << lifetimeExamples
<< ", Lifetime QPS = "
<< (static_cast<double>(lifetimeExamples) / lifetimeSeconds)
<< ", Window Examples = " << windowExamples << ", Window QPS = "
<< (static_cast<double>(windowExamples) / windowSeconds);
return true;
}
};
}