From b57dbfe6ec530a7c90dc3016941a7f9aa22f26b1 Mon Sep 17 00:00:00 2001 From: RJ Ascani Date: Sat, 15 Jul 2023 00:29:22 +0000 Subject: [PATCH 1/2] Fix benchmarking utils on RISC-V The generic benchmarking utilities added in PR 2125 did not compile on RISC-V due to two separate issues: * An incorrect format specifier for int32_t on RISC-V. This is resolved by using PRId32 instead of %ld or %d. * The fileno() is undeclared with the RISC-V toolchain, similar to how it is with the Embedded ARM toolchain. This PR resolves this by forgoing the fstat() check on file size (as this is what used fileno), and instead attempting to read the maximum number of bytes we can fit in the model buffer. We can then use feof() to verify that we read the entirety of the model, and error out if we did not. This solution also eliminates needing to worry about different file types, such as how the Xtensa simulator treats files from the host system as character devices. BUG=2129 --- .../benchmarking/generic_model_benchmark.cc | 35 ++++--------------- .../micro/tools/benchmarking/log_utils.cc | 7 ++-- 2 files changed, 9 insertions(+), 33 deletions(-) diff --git a/tensorflow/lite/micro/tools/benchmarking/generic_model_benchmark.cc b/tensorflow/lite/micro/tools/benchmarking/generic_model_benchmark.cc index 1c2f4b9791d..4249deb320c 100644 --- a/tensorflow/lite/micro/tools/benchmarking/generic_model_benchmark.cc +++ b/tensorflow/lite/micro/tools/benchmarking/generic_model_benchmark.cc @@ -13,6 +13,7 @@ See the License for the specific language governing permissions and limitations under the License. ==============================================================================*/ +#include #include #include @@ -76,37 +77,15 @@ void SetRandomInput(const uint32_t random_seed, } bool ReadFile(const char* file_name, void* buffer, size_t buffer_size) { - // Obtain the file size using fstat, or report an error if that fails. std::unique_ptr file(fopen(file_name, "rb"), fclose); - struct stat sb; - -// For CMSIS_NN, the compilation is failing with the following error -// 'fileno' was not declared in this scope -// TODO(b/290988791): Investigate why fileno is not defined in arm toolchain. -#if defined(CMSIS_NN) - if (fstat(file.get()->_file, &sb) != 0) { -#else - if (fstat(fileno(file.get()), &sb) != 0) { -#endif - MicroPrintf("Failed to get file size of: %s\n", file_name); - return false; - } - - if (!buffer) { - MicroPrintf("Malloc of buffer to hold copy of '%s' failed\n", file_name); - return false; - } - if (S_ISREG(sb.st_mode) != 0 && - (sb.st_size < 0 || (static_cast(sb.st_size) > buffer_size))) { - MicroPrintf( - "Buffer size (%ld) to hold the model is less than required %ld.\n", - buffer_size, sb.st_size); + fread(buffer, sizeof(char), buffer_size, file.get()); + if (ferror(file.get())) { + MicroPrintf("Unable to read model file: %d\n", ferror(file.get())); return false; } - - if (!fread(buffer, sizeof(char), sb.st_size, file.get())) { - MicroPrintf("Unable to read the model file or the model file is empty.\n"); + if (!feof(file.get())) { + MicroPrintf("Model buffer is too small for the model.\n"); return false; } @@ -173,4 +152,4 @@ int Benchmark(const char* model_file_name) { } // namespace } // namespace tflite -int main(int argc, char** argv) { return tflite::Benchmark(argv[1]); } \ No newline at end of file +int main(int argc, char** argv) { return tflite::Benchmark(argv[1]); } diff --git a/tensorflow/lite/micro/tools/benchmarking/log_utils.cc b/tensorflow/lite/micro/tools/benchmarking/log_utils.cc index 8ac4ca39071..808e465b514 100644 --- a/tensorflow/lite/micro/tools/benchmarking/log_utils.cc +++ b/tensorflow/lite/micro/tools/benchmarking/log_utils.cc @@ -15,6 +15,7 @@ limitations under the License. #include "tensorflow/lite/micro/tools/benchmarking/log_utils.h" +#include #include #include @@ -90,11 +91,7 @@ void PrettyPrintTableHeader(PrettyPrintType type, const char* table_name) { template <> void FormatNumber(char* output, int32_t value) { -#if defined(HEXAGON) || defined(CMSIS_NN) - sprintf(output, "%ld", value); // NOLINT: sprintf required. -#else - sprintf(output, "%d", value); // NOLINT: sprintf required. -#endif + sprintf(output, "%" PRId32, value); // NOLINT: sprintf required. } template <> From b5378e3785883aa3fc346183f1515be5a8d2221a Mon Sep 17 00:00:00 2001 From: RJ Ascani Date: Sat, 15 Jul 2023 14:15:15 +0000 Subject: [PATCH 2/2] Add return value check for fread --- .../micro/tools/benchmarking/generic_model_benchmark.cc | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tensorflow/lite/micro/tools/benchmarking/generic_model_benchmark.cc b/tensorflow/lite/micro/tools/benchmarking/generic_model_benchmark.cc index 4249deb320c..c1db8fa9cf3 100644 --- a/tensorflow/lite/micro/tools/benchmarking/generic_model_benchmark.cc +++ b/tensorflow/lite/micro/tools/benchmarking/generic_model_benchmark.cc @@ -79,7 +79,8 @@ void SetRandomInput(const uint32_t random_seed, bool ReadFile(const char* file_name, void* buffer, size_t buffer_size) { std::unique_ptr file(fopen(file_name, "rb"), fclose); - fread(buffer, sizeof(char), buffer_size, file.get()); + const size_t bytes_read = + fread(buffer, sizeof(char), buffer_size, file.get()); if (ferror(file.get())) { MicroPrintf("Unable to read model file: %d\n", ferror(file.get())); return false; @@ -88,6 +89,10 @@ bool ReadFile(const char* file_name, void* buffer, size_t buffer_size) { MicroPrintf("Model buffer is too small for the model.\n"); return false; } + if (bytes_read == 0) { + MicroPrintf("No bytes read from model file.\n"); + return false; + } return true; }