Add a way to set image bmp, dump result and change log level of SOC graph transferer
Change: 143692340
This commit is contained in:
parent
a329a9a1b2
commit
93ee6cc577
tensorflow/core/kernels/hexagon
@ -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
|
||||
|
@ -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_;
|
||||
|
@ -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();
|
||||
|
Loading…
Reference in New Issue
Block a user