Add a way to set image bmp, dump result and change log level of SOC graph transferer

Change: 143692340
This commit is contained in:
A. Unique TensorFlower 2017-01-05 11:58:26 -08:00 committed by TensorFlower Gardener
parent a329a9a1b2
commit 93ee6cc577
3 changed files with 114 additions and 13 deletions

View File

@ -15,6 +15,8 @@ limitations under the License.
#include "tensorflow/core/kernels/hexagon/hexagon_control_wrapper.h"
#include <queue>
#ifdef USE_HEXAGON_LIBS
#include "tensorflow/core/platform/hexagon/soc_interface.h"
#include "tensorflow/core/platform/profile_utils/cpu_utils.h"
@ -23,12 +25,19 @@ limitations under the License.
namespace tensorflow {
const bool SHOW_DBG_IN_SOC = false;
const bool DBG_DUMP_RESULT = true;
const bool DBG_USE_DUMMY_INPUT = false;
#ifdef USE_HEXAGON_LIBS
int HexagonControlWrapper::GetVersion() {
return soc_interface_GetSocControllerVersion();
}
bool HexagonControlWrapper::Init() { return soc_interface_Init(); }
bool HexagonControlWrapper::Init() {
soc_interface_SetLogLevel(SHOW_DBG_IN_SOC ? -1 /* debug */ : 0 /* info */);
return soc_interface_Init();
}
bool HexagonControlWrapper::Finalize() { return soc_interface_Finalize(); }
bool HexagonControlWrapper::SetupGraph(
@ -169,14 +178,22 @@ bool HexagonControlWrapper::TeardownGraph() {
bool HexagonControlWrapper::FillInputNode(const string node_name,
const ByteArray bytes) {
uint64 byte_size;
// TODO(satok): Use arguments instead of dummy input
const int x = 1;
const int y = 299;
const int z = 299;
const int d = 3;
const int array_length = x * y * z * d;
const int byte_size = array_length * sizeof(float);
dummy_input_float_.resize(array_length);
if (DBG_USE_DUMMY_INPUT) {
const int x = 1;
const int y = 299;
const int z = 299;
const int d = 3;
const int array_length = x * y * z * d;
byte_size = array_length * sizeof(float);
dummy_input_float_.resize(array_length);
} else {
CHECK(std::get<2>(bytes) == DT_FLOAT);
byte_size = std::get<1>(bytes);
dummy_input_float_.resize(byte_size / sizeof(float));
std::memcpy(dummy_input_float_.data(), std::get<0>(bytes), byte_size);
}
return soc_interface_FillInputNodeFloat(
1, 299, 299, 3, reinterpret_cast<uint8 *>(dummy_input_float_.data()),
byte_size);
@ -188,8 +205,15 @@ bool HexagonControlWrapper::ReadOutputNode(
ByteArray output;
soc_interface_ReadOutputNodeFloat(node_name.c_str(), &std::get<0>(output),
&std::get<1>(output));
// TODO: Accept all results
std::get<2>(output) = DT_FLOAT;
outputs->emplace_back(output);
if (DBG_DUMP_RESULT) {
const int byte_size = std::get<1>(output);
const int element_count = byte_size / sizeof(float);
const float* float_array = reinterpret_cast<float*>(std::get<0>(output));
DumpTopNFloatResults(float_array, element_count, 10 /* top_n */);
}
return true;
}
@ -211,4 +235,19 @@ bool HexagonControlWrapper::ReadOutputNode(const string,
}
#endif
void HexagonControlWrapper::DumpTopNFloatResults(const float* data,
const float element_count,
const int top_n) {
std::priority_queue<std::tuple<float, int>> queue;
for (int i = 0; i < element_count; ++i) {
queue.emplace(data[i], i);
}
LOG(INFO) << "=== Dump ranking ===";
for (int i = 0; i < top_n; ++i) {
const std::tuple<float, int>& entry = queue.top();
LOG(INFO) << i << ": " << std::get<1>(entry) << ", " << std::get<0>(entry);
queue.pop();
}
}
} // namespace tensorflow

View File

@ -46,6 +46,9 @@ class HexagonControlWrapper final : public ISocControlWrapper {
// CAVEAT: Need offset as HVX library reserves some ids
static constexpr int NODE_ID_OFFSET = 0x10000;
void DumpTopNFloatResults(const float *data, const float element_count,
const int top_n);
// Dummy float array for input node.
// TODO(satok): Use actual data passed by FillInputNode and remove
std::vector<float> dummy_input_float_;

View File

@ -25,25 +25,36 @@ limitations under the License.
#include "tensorflow/core/kernels/hexagon/hexagon_control_wrapper.h"
#include "tensorflow/core/kernels/hexagon/hexagon_ops_definitions.h"
#include "tensorflow/core/kernels/hexagon/i_graph_transfer_ops_definitions.h"
#include "tensorflow/core/kernels/hexagon/i_soc_control_wrapper.h"
#include "tensorflow/core/lib/core/casts.h"
#include "tensorflow/core/lib/core/status.h"
#include "tensorflow/core/lib/io/path.h"
#include "tensorflow/core/platform/env.h"
#include "tensorflow/core/platform/test.h"
namespace tensorflow {
using ByteArray = ISocControlWrapper::ByteArray;
const bool DBG_DUMP_FLOAT_DATA = false;
const int WIDTH = 299;
const int HEIGHT = 299;
const int DEPTH = 3;
// CAVEAT: This test only runs when you specify hexagon library using
// makefile.
// TODO(satok): Make this generic so that this can run without any
// additionanl steps.
#ifdef USE_HEXAGON_LIBS
TEST(GraphTransferer, RunInceptionV3OnHexagonExample) {
const string filename =
const string image_filename = "/data/local/tmp/img_299x299.bmp";
const string model_filename =
"/data/local/tmp/tensorflow_inception_v3_stripped_optimized_quantized.pb";
const IGraphTransferOpsDefinitions* ops_definitions =
&HexagonOpsDefinitions::getInstance();
std::vector<GraphTransferer::InputNodeInfo> input_node_info_list = {
GraphTransferer::InputNodeInfo{"Mul",
Tensor{DT_FLOAT, {1, 299, 299, 3}}}};
GraphTransferer::InputNodeInfo{
"Mul", Tensor{DT_FLOAT, {1, WIDTH, HEIGHT, DEPTH}}}};
std::vector<string> output_node_names = {"softmax"};
const bool is_text_proto = false;
@ -51,7 +62,7 @@ TEST(GraphTransferer, RunInceptionV3OnHexagonExample) {
GraphTransferer gt;
gt.EnableStrictCheckMode(false);
Status status = gt.LoadGraphFromProtoFile(
*ops_definitions, filename, input_node_info_list, output_node_names,
*ops_definitions, model_filename, input_node_info_list, output_node_names,
is_text_proto, true /* dry_run_for_unknown_shape */, &output_tensor_info);
ASSERT_TRUE(status.ok()) << status;
@ -60,6 +71,54 @@ TEST(GraphTransferer, RunInceptionV3OnHexagonExample) {
ASSERT_GE(version, 1);
LOG(INFO) << "Hexagon controller version is " << version;
// Read the data from the bitmap file into memory
string bmp;
TF_CHECK_OK(ReadFileToString(Env::Default(), image_filename, &bmp));
const int fsize = bmp.size();
LOG(INFO) << "Read " << image_filename << ", size = " << fsize << "bytes";
const int64 pixel_count = WIDTH * HEIGHT * DEPTH;
uint8* const img_bytes = bit_cast<uint8*>(bmp.data());
const int header_size = *(reinterpret_cast<int*>(img_bytes + 10));
const int size = *(reinterpret_cast<int*>(img_bytes + 14));
const int width = *(reinterpret_cast<int*>(img_bytes + 18));
const int height = *(reinterpret_cast<int*>(img_bytes + 22));
LOG(INFO) << header_size << ", " << size << ", " << width << ", " << height;
CHECK(fsize >= (WIDTH + 1) * WIDTH * 3 + header_size);
uint8* const bmp_pixels = &img_bytes[header_size];
std::vector<float> img_floats(pixel_count);
int src_pixel_index = 0;
CHECK(pixel_count % 3 == 0);
for (int i = 0; i < pixel_count / 3; ++i) {
const int src_pos = 3 * src_pixel_index;
const int dst_pos = 3 * i;
++src_pixel_index;
CHECK(src_pos + 2 + header_size < fsize);
CHECK(dst_pos + 2 < pixel_count);
// Convert (B, G, R) in bitmap to (R, G, B)
img_floats[dst_pos] =
(static_cast<float>(bmp_pixels[src_pos + 2]) - 128.0f) / 128.0f;
img_floats[dst_pos + 1] =
(static_cast<float>(bmp_pixels[src_pos + 1]) - 128.0f) / 128.0f;
img_floats[dst_pos + 2] =
(static_cast<float>(bmp_pixels[src_pos]) - 128.0f) / 128.0f;
if (DBG_DUMP_FLOAT_DATA) {
LOG(INFO) << i << " (" << img_floats[dst_pos] << ", "
<< img_floats[dst_pos + 1] << ", " << img_floats[dst_pos + 2]
<< ") (" << static_cast<int>(bmp_pixels[src_pos + 2]) << ", "
<< static_cast<int>(bmp_pixels[src_pos + 1]) << ", "
<< static_cast<int>(bmp_pixels[src_pos]) << ")";
}
if (src_pixel_index % (WIDTH + 1) == (WIDTH - 1)) {
// skip bmp padding
++src_pixel_index;
}
}
const ByteArray ba =
std::make_tuple(reinterpret_cast<uint8*>(img_floats.data()),
pixel_count * sizeof(float), DT_FLOAT);
// 1. Initialize hexagon
hexagon_control_wrapper.Init();
@ -67,7 +126,7 @@ TEST(GraphTransferer, RunInceptionV3OnHexagonExample) {
hexagon_control_wrapper.SetupGraph(gt);
// 3. Fill input node's output
hexagon_control_wrapper.FillInputNode("Mul", {});
hexagon_control_wrapper.FillInputNode("Mul", ba);
// 4. Execute graph
hexagon_control_wrapper.ExecuteGraph();