aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Chris Ying <chrisying@google.com>2018-02-20 12:16:49 -0800
committerGravatar TensorFlower Gardener <gardener@tensorflow.org>2018-02-20 12:20:53 -0800
commitc07a6e6568b776037f052bc0d385a509ec2647aa (patch)
tree1d6694f27b11be6707bb0b75501cd68300a113c5
parent706089cf71af3755cc911722b596bae948d1e5b4 (diff)
Add Timestamp Op which returns the current timestamp during graph execution
PiperOrigin-RevId: 186342760
-rw-r--r--tensorflow/core/api_def/base_api/api_def_Timestamp.pbtxt10
-rw-r--r--tensorflow/core/kernels/logging_ops.cc19
-rw-r--r--tensorflow/core/kernels/logging_ops_test.cc25
-rw-r--r--tensorflow/core/ops/logging_ops.cc5
-rw-r--r--tensorflow/python/ops/control_flow_ops.py1
-rw-r--r--tensorflow/python/ops/logging_ops.py1
-rw-r--r--tensorflow/python/ops/standard_ops.py5
-rw-r--r--tensorflow/tools/api/golden/tensorflow.pbtxt4
8 files changed, 68 insertions, 2 deletions
diff --git a/tensorflow/core/api_def/base_api/api_def_Timestamp.pbtxt b/tensorflow/core/api_def/base_api/api_def_Timestamp.pbtxt
new file mode 100644
index 0000000000..bf2d07bcf5
--- /dev/null
+++ b/tensorflow/core/api_def/base_api/api_def_Timestamp.pbtxt
@@ -0,0 +1,10 @@
+op {
+ graph_op_name: "Timestamp"
+ summary: "Provides the time since epoch in seconds."
+ description: <<END
+Returns the timestamp as a `float64` for seconds since the Unix epoch.
+
+Note: the timestamp is computed when the op is executed, not when it is added
+to the graph.
+END
+}
diff --git a/tensorflow/core/kernels/logging_ops.cc b/tensorflow/core/kernels/logging_ops.cc
index bacf3e7740..6b6a14e9a7 100644
--- a/tensorflow/core/kernels/logging_ops.cc
+++ b/tensorflow/core/kernels/logging_ops.cc
@@ -90,4 +90,23 @@ class PrintOp : public OpKernel {
REGISTER_KERNEL_BUILDER(Name("Print").Device(DEVICE_CPU), PrintOp);
+class TimestampOp : public OpKernel {
+ public:
+ explicit TimestampOp(OpKernelConstruction* context) : OpKernel(context) {}
+
+ void Compute(OpKernelContext* context) override {
+ TensorShape output_shape; // Default shape is 0 dim, 1 element
+ Tensor* output_tensor = nullptr;
+ OP_REQUIRES_OK(context,
+ context->allocate_output(0, output_shape, &output_tensor));
+
+ auto output_scalar = output_tensor->scalar<double>();
+ double now_us = static_cast<double>(Env::Default()->NowMicros());
+ double now_s = now_us / 1000000;
+ output_scalar() = now_s;
+ }
+};
+
+REGISTER_KERNEL_BUILDER(Name("Timestamp").Device(DEVICE_CPU), TimestampOp);
+
} // end namespace tensorflow
diff --git a/tensorflow/core/kernels/logging_ops_test.cc b/tensorflow/core/kernels/logging_ops_test.cc
index 9cf669a7ef..5e6958f364 100644
--- a/tensorflow/core/kernels/logging_ops_test.cc
+++ b/tensorflow/core/kernels/logging_ops_test.cc
@@ -13,6 +13,9 @@ See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
+#include <chrono>
+#include <thread>
+
#include "tensorflow/core/framework/fake_input.h"
#include "tensorflow/core/framework/node_def_builder.h"
#include "tensorflow/core/framework/tensor.h"
@@ -96,5 +99,27 @@ TEST_F(PrintingGraphTest, FirstNSuccess) {
test::ExpectTensorEqual<int32>(expected, *GetOutput(0));
}
+class TimestampTest : public OpsTestBase {
+ protected:
+ Status Init() {
+ TF_CHECK_OK(NodeDefBuilder("op", "Timestamp").Finalize(node_def()));
+ return InitOp();
+ }
+};
+
+TEST_F(TimestampTest, WaitAtLeast) {
+ TF_ASSERT_OK(Init());
+ TF_ASSERT_OK(RunOpKernel());
+ double ts1 = *((*GetOutput(0)).flat<double>().data());
+
+ // wait 1 second
+ std::this_thread::sleep_for(std::chrono::seconds(1));
+
+ TF_ASSERT_OK(RunOpKernel());
+ double ts2 = *((*GetOutput(0)).flat<double>().data());
+
+ EXPECT_LE(1.0, ts2 - ts1);
+}
+
} // end namespace
} // end namespace tensorflow
diff --git a/tensorflow/core/ops/logging_ops.cc b/tensorflow/core/ops/logging_ops.cc
index d263dc25b2..fbde692e95 100644
--- a/tensorflow/core/ops/logging_ops.cc
+++ b/tensorflow/core/ops/logging_ops.cc
@@ -111,4 +111,9 @@ REGISTER_OP("MergeSummary")
.Attr("N : int >= 1")
.SetShapeFn(shape_inference::ScalarShape);
+REGISTER_OP("Timestamp")
+ .Output("ts: float64")
+ .SetIsStateful()
+ .SetShapeFn(shape_inference::ScalarShape);
+
} // end namespace tensorflow
diff --git a/tensorflow/python/ops/control_flow_ops.py b/tensorflow/python/ops/control_flow_ops.py
index c33f351289..f77f0050f7 100644
--- a/tensorflow/python/ops/control_flow_ops.py
+++ b/tensorflow/python/ops/control_flow_ops.py
@@ -44,6 +44,7 @@ See the @{$python/control_flow_ops} guide.
@@add_check_numerics_ops
@@Assert
@@Print
+@@timestamp
"""
# pylint: disable=g-bad-name
from __future__ import absolute_import
diff --git a/tensorflow/python/ops/logging_ops.py b/tensorflow/python/ops/logging_ops.py
index eadbc1b7c3..3757109c95 100644
--- a/tensorflow/python/ops/logging_ops.py
+++ b/tensorflow/python/ops/logging_ops.py
@@ -356,3 +356,4 @@ ops.NotDifferentiable("AudioSummary")
ops.NotDifferentiable("AudioSummaryV2")
ops.NotDifferentiable("MergeSummary")
ops.NotDifferentiable("ScalarSummary")
+ops.NotDifferentiable("Timestamp")
diff --git a/tensorflow/python/ops/standard_ops.py b/tensorflow/python/ops/standard_ops.py
index f6d9111009..b62e556967 100644
--- a/tensorflow/python/ops/standard_ops.py
+++ b/tensorflow/python/ops/standard_ops.py
@@ -60,6 +60,7 @@ from tensorflow.python.ops.io_ops import *
from tensorflow.python.ops.linalg_ops import *
from tensorflow.python.ops.logging_ops import Print
from tensorflow.python.ops.logging_ops import get_summary_op
+from tensorflow.python.ops.logging_ops import timestamp
from tensorflow.python.ops.lookup_ops import initialize_all_tables
from tensorflow.python.ops.lookup_ops import tables_initializer
from tensorflow.python.ops.manip_ops import *
@@ -232,7 +233,7 @@ _allowed_symbols_clip_ops = [
"global_norm",
]
-_allowed_symbols_image_ops = [
+_allowed_symbols_logging_ops = [
# Documented in training.py.
# We are not importing training.py to avoid complex dependencies.
"audio_summary",
@@ -262,8 +263,8 @@ _allowed_symbols = (_allowed_symbols_array_ops +
_allowed_symbols_clip_ops +
_allowed_symbols_control_flow_ops +
_allowed_symbols_functional_ops +
- _allowed_symbols_image_ops +
_allowed_symbols_gradients +
+ _allowed_symbols_logging_ops +
_allowed_symbols_math_ops +
_allowed_symbols_variable_scope_ops +
_allowed_symbols_misc +
diff --git a/tensorflow/tools/api/golden/tensorflow.pbtxt b/tensorflow/tools/api/golden/tensorflow.pbtxt
index e8890e9cc0..2333736583 100644
--- a/tensorflow/tools/api/golden/tensorflow.pbtxt
+++ b/tensorflow/tools/api/golden/tensorflow.pbtxt
@@ -1989,6 +1989,10 @@ tf_module {
argspec: "args=[\'input\', \'multiples\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], "
}
member_method {
+ name: "timestamp"
+ argspec: "args=[\'name\'], varargs=None, keywords=None, defaults=[\'None\'], "
+ }
+ member_method {
name: "to_bfloat16"
argspec: "args=[\'x\', \'name\'], varargs=None, keywords=None, defaults=[\'ToBFloat16\'], "
}