blob: 002de6fb6e89d4be60f8b8e8b944d69022717830 [file] [log] [blame]
/* Copyright 2019 The TensorFlow Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
#include <sstream>
#include "tensorflow/c/kernels.h"
#include "tensorflow/c/ops.h"
#include "tensorflow/c/tf_tensor.h"
#include "tensorflow/core/framework/common_shape_fns.h"
#include "tensorflow/core/framework/op.h"
#include "tensorflow/core/framework/selective_registration.h"
#include "tensorflow/core/framework/shape_inference.h"
#include "tensorflow/core/platform/macros.h"
#include "tensorflow/core/framework/summary.pb.h"
#include "tensorflow/core/platform/protobuf.h"
#include "tensorflow/core/framework/register_types.h"
#include "tensorflow/core/framework/types.h"
#include<iostream>
// TODO: Copy over Summary Scalar Op Doc
static void* SummaryScalarOp_Create(TF_OpKernelConstruction* ctx) {
// TODO: replace with a void* pointer type later
void* ptr;
return ptr;
}
static void SummaryScalarOp_Delete(void* kernel) {
return;
}
bool IsSameSize(TF_Tensor* tensor1, TF_Tensor* tensor2){
if (TF_NumDims(tensor1) != TF_NumDims(tensor2)){
return false;
}
for(int d = 0; d < TF_NumDims(tensor1); d++){
if (TF_Dim(tensor1, d) != TF_Dim(tensor2, d)){
return false;
}
}
return true;
}
template<typename T>
static void SummaryScalarOp_Compute(void* kernel, TF_OpKernelContext* ctx) {
TF_Tensor* tags;
TF_Tensor* values;
TF_Status* status = TF_NewStatus();
TF_GetInput(ctx, 0, &tags, status);
if (TF_GetCode(status) == TF_OK){
TF_GetInput(ctx, 1, &values, status);
}
if (TF_GetCode(status) == TF_OK) {
if (!IsSameSize(tags, values)) {
std::ostringstream err;
err << "tags and values not the same shape: " << TF_ShapeDebugString(tags)
<< " != " << TF_ShapeDebugString(values);
TF_SetStatus(status, TF_INVALID_ARGUMENT, err.str().c_str());
}
}
// Copy tag and string data into summary protobuf
tensorflow::Summary s;
if (TF_GetCode(status) == TF_OK) {
// Convert tags and values tensor to array to access elements by index
auto tags_array = static_cast<TF_TString*>(TF_TensorData(tags));
auto values_array = static_cast<T*>(TF_TensorData(values));
for (int i = 0; i < TF_TensorElementCount(tags); ++i){
tensorflow::Summary::Value* v = s.add_value();
v->set_tag(TF_TString_GetDataPointer(&tags_array[i]),
TF_TString_GetSize(&tags_array[i]));
v->set_simple_value(float(values_array[i]));
}
TF_Tensor* summary_tensor = TF_AllocateOutput(ctx, 0,
TF_ExpectedOutputDataType(ctx, 0), nullptr, 0,
sizeof(TF_TString), status);
if (TF_GetCode(status) == TF_OK){
SerializeToTString(s, static_cast<tensorflow::tstring*>
(TF_TensorData(summary_tensor)));
}
TF_DeleteTensor(summary_tensor);
}
if (TF_GetCode(status) != TF_OK) {
TF_OpKernelContext_Failure(ctx, status);
}
TF_DeleteStatus(status);
TF_DeleteTensor(tags);
}
template <typename T>
void RegisterSummaryScalarOpKernel() {
TF_Status* status = TF_NewStatus();
{
auto* builder = TF_NewKernelBuilder("SummaryScalar", tensorflow::DEVICE_CPU,
&SummaryScalarOp_Create, &SummaryScalarOp_Compute<T>,
&SummaryScalarOp_Delete);
TF_KernelBuilder_TypeConstraint(builder, "T", static_cast<TF_DataType>(tensorflow::DataTypeToEnum<T>::v()), status);
CHECK_EQ(TF_OK, TF_GetCode(status))
<< "Error while adding type constraint";
TF_RegisterKernelBuilder("SummaryScalarOp", builder, status);
CHECK_EQ(TF_OK, TF_GetCode(status))
<< "Error while registering Summary Scalar kernel";
}
// #if GOOGLE_CUDA
// {
// auto* builder = TF_NewKernelBuilder("SummaryScalar", tensorflow::DEVICE_GPU,
// &SummaryScalarOp_Create, &SummaryScalarOp_Compute<T>,
// &SummaryScalarOp_Delete);
// TF_RegisterKernelBuilder("SummaryScalar", builder, status);
// CHECK_EQ(TF_OK, TF_GetCode(status))
// << "Error while registering CUDA SummaryScalar kernel";
// }
// #endif
TF_DeleteStatus(status);
}
// A dummy static variable initialized by a lambda whose side-effect is to
// register the bitcast kernel.
TF_ATTRIBUTE_UNUSED static bool IsSummaryScalarOpKernelRegistered = []() {
if (SHOULD_REGISTER_OP_KERNEL("SummaryScalarOp")) {
RegisterSummaryScalarOpKernel<tensorflow::int64>();
RegisterSummaryScalarOpKernel<tensorflow::int32>();
RegisterSummaryScalarOpKernel<tensorflow::uint16>();
RegisterSummaryScalarOpKernel<tensorflow::int16>();
RegisterSummaryScalarOpKernel<tensorflow::uint8>();
RegisterSummaryScalarOpKernel<Eigen::half>();
RegisterSummaryScalarOpKernel<tensorflow::bfloat16>();
RegisterSummaryScalarOpKernel<float>();
RegisterSummaryScalarOpKernel<double>();
}
return true;
}();