Skip to content
This repository was archived by the owner on Jul 22, 2026. It is now read-only.

Commit 040794f

Browse files
committed
batch 32 for accuracy
1 parent 4eb3771 commit 040794f

4 files changed

Lines changed: 245 additions & 61 deletions

File tree

app/Graph/acc_check.cpp

Lines changed: 225 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,14 @@
1-
#include <algorithm>
1+
2+
#ifndef WIN32_LEAN_AND_MEAN
3+
#define WIN32_LEAN_AND_MEAN
4+
#endif
5+
#include <windows.h>
6+
#include <psapi.h>
7+
#pragma comment(lib, "psapi.lib")
8+
#include <crtdbg.h>
9+
#include <algorithm>
10+
#include <chrono>
11+
#include <cmath>
212
#include <filesystem>
313
#include <iomanip>
414
#include <numeric>
@@ -7,17 +17,82 @@
717

818
#include "build.hpp"
919

20+
class MemoryLogger {
21+
private:
22+
std::chrono::steady_clock::time_point start_time;
23+
size_t peak_memory = 0;
24+
size_t initial_memory = 0;
25+
26+
size_t getProcessMemory() {
27+
HANDLE hProcess = GetCurrentProcess();
28+
PROCESS_MEMORY_COUNTERS pmc;
29+
pmc.cb = sizeof(PROCESS_MEMORY_COUNTERS);
30+
31+
if (GetProcessMemoryInfo(hProcess, &pmc, sizeof(pmc))) {
32+
return pmc.WorkingSetSize / (1024 * 1024);
33+
}
34+
return 0;
35+
}
36+
37+
public:
38+
MemoryLogger() {
39+
start_time = std::chrono::steady_clock::now();
40+
initial_memory = getProcessMemory();
41+
log("START");
42+
}
43+
44+
void log(const char* stage) {
45+
auto now = std::chrono::steady_clock::now();
46+
auto elapsed =
47+
std::chrono::duration_cast<std::chrono::seconds>(now - start_time)
48+
.count();
49+
50+
size_t current = getProcessMemory();
51+
if (current > peak_memory) peak_memory = current;
52+
53+
std::cout << "[" << std::setw(4) << elapsed << "s] " << std::setw(30)
54+
<< stage << " | "
55+
<< "PROCESS MEM: " << std::setw(6) << current << " MB"
56+
<< " (PEAK: " << std::setw(6) << peak_memory << " MB)"
57+
<< " (DELTA: " << std::setw(4) << (current - initial_memory)
58+
<< " MB)\n";
59+
}
60+
61+
~MemoryLogger() {
62+
log("END");
63+
std::cout << "====================================\n";
64+
std::cout << "PEAK PROCESS MEMORY: " << peak_memory << " MB\n";
65+
std::cout << "INITIAL PROCESS MEMORY: " << initial_memory << " MB\n";
66+
std::cout << "FINAL PROCESS MEMORY: " << getProcessMemory() << " MB\n";
67+
if (getProcessMemory() > initial_memory + 10) {
68+
std::cout << "WARNING: Process memory growth! (+"
69+
<< (getProcessMemory() - initial_memory) << " MB)\n";
70+
} else {
71+
std::cout << "OK: No significant process memory growth\n";
72+
}
73+
}
74+
};
75+
76+
MemoryLogger g_memLogger;
77+
78+
#define LOG_MEM(stage) g_memLogger.log(stage)
79+
1080
namespace fs = std::filesystem;
1181
using namespace it_lab_ai;
1282

1383
int main(int argc, char* argv[]) {
84+
LOG_MEM("Program start");
85+
1486
std::string model_name = "alexnet_mnist";
1587
RuntimeOptions options;
1688
size_t num_photo = 1000;
89+
size_t batch_size = 32;
1790

1891
for (int i = 1; i < argc; ++i) {
1992
if (std::string(argv[i]) == "--model" && i + 1 < argc) {
2093
model_name = argv[++i];
94+
} else if (std::string(argv[i]) == "--batch" && i + 1 < argc) {
95+
batch_size = std::stoi(argv[++i]);
2196
} else if (std::string(argv[i]) == "--onednn") {
2297
options.backend = Backend::kOneDnn;
2398
if (options.par_backend != ParBackend::kSeq) {
@@ -64,6 +139,8 @@ int main(int argc, char* argv[]) {
64139
}
65140
}
66141

142+
LOG_MEM("After args parsing");
143+
67144
std::string dataset_path;
68145
if (model_name == "alexnet_mnist") {
69146
dataset_path = MNIST_PATH;
@@ -75,8 +152,10 @@ int main(int argc, char* argv[]) {
75152
std::vector<int> input_shape = get_input_shape_from_json(json_path);
76153

77154
std::cout << '\n';
78-
155+
int batch_count = 0;
79156
if (model_name == "alexnet_mnist") {
157+
LOG_MEM("MNIST start");
158+
80159
std::vector<size_t> counts = {979, 1134, 1031, 1009, 981,
81160
891, 957, 1027, 973, 1008};
82161
int stat = 0;
@@ -144,15 +223,20 @@ int main(int argc, char* argv[]) {
144223
(static_cast<double>(stat) / static_cast<double>(sum + 10)) * 100;
145224
std::cout << "Stat: " << std::fixed << std::setprecision(2) << percentage
146225
<< "%" << '\n';
226+
227+
LOG_MEM("MNIST end");
147228
return 0;
148229
}
149230

231+
LOG_MEM("ImageNet start");
232+
150233
std::vector<size_t> counts(1000, 0);
151234
std::vector<std::string> image_paths;
152235
std::vector<int> true_labels;
153236
std::vector<float> all_image_data;
154237
size_t total_images = 0;
155238

239+
LOG_MEM("Counting classes");
156240
for (int class_id = 0; class_id < 1000; ++class_id) {
157241
std::ostringstream folder_oss;
158242
folder_oss << std::setw(5) << std::setfill('0') << class_id;
@@ -176,13 +260,16 @@ int main(int argc, char* argv[]) {
176260
int height = input_shape[2];
177261
int width = input_shape[3];
178262
size_t image_size = channels * height * width;
263+
size_t output_classes = 1000;
179264

265+
LOG_MEM("Reserving memory");
180266
all_image_data.reserve(num_photo * image_size);
181267
image_paths.reserve(num_photo);
182268
true_labels.reserve(num_photo);
183269

184270
total_images = 0;
185271

272+
LOG_MEM("Loading images start");
186273
for (int class_id = 0; class_id < 1000; ++class_id) {
187274
size_t need_from_class = images_per_class_base;
188275
if (remaining > 0) {
@@ -230,72 +317,148 @@ int main(int argc, char* argv[]) {
230317
std::cout << "Warning: Class " << class_id << " has only " << taken
231318
<< " images (needed " << need_from_class << ")" << '\n';
232319
}
320+
321+
if (class_id % 100 == 0 && class_id > 0) {
322+
char buf[50];
323+
sprintf(buf, "Class %d", class_id);
324+
LOG_MEM(buf);
325+
}
233326
}
234327

328+
LOG_MEM("Images loaded");
329+
235330
if (total_images != num_photo) {
236331
std::cout << "Warning: Requested " << num_photo << " images but loaded "
237332
<< total_images << " due to insufficient data" << '\n';
238333
num_photo = total_images;
239334
}
240335

241-
it_lab_ai::Shape input_shape_imagenet(
242-
{num_photo, static_cast<size_t>(channels), static_cast<size_t>(height),
243-
static_cast<size_t>(width)});
244-
it_lab_ai::Tensor input =
245-
it_lab_ai::make_tensor(all_image_data, input_shape_imagenet);
246-
247-
size_t output_classes = 1000;
248-
it_lab_ai::Shape output_shape({num_photo, output_classes});
249-
it_lab_ai::Tensor output =
250-
it_lab_ai::Tensor(output_shape, it_lab_ai::Type::kFloat);
251-
252-
Graph graph;
253-
build_graph(graph, input, output, json_path, options, false);
254-
graph.inference(options);
255-
print_time_stats(graph);
256-
257-
std::vector<std::vector<float>> processed_outputs;
258-
const std::vector<float>& raw_output = *output.as<float>();
259-
260-
for (size_t i = 0; i < num_photo; ++i) {
261-
std::vector<float> single_output(
262-
raw_output.begin() + i * output_classes,
263-
raw_output.begin() + (i + 1) * output_classes);
264-
std::vector<float> processed_output =
265-
process_model_output(single_output, model_name);
266-
processed_outputs.push_back(processed_output);
267-
}
268-
269336
int correct_predictions_top1 = 0;
270337
int correct_predictions_top5 = 0;
271-
for (size_t i = 0; i < processed_outputs.size(); ++i) {
272-
int true_label = true_labels[i];
273-
const std::vector<float>& probabilities = processed_outputs[i];
274-
275-
std::vector<size_t> indices(probabilities.size());
276-
std::iota(indices.begin(), indices.end(), 0);
277-
std::sort(indices.begin(), indices.end(), [&](size_t a, size_t b) {
278-
return probabilities[a] > probabilities[b];
279-
});
280-
281-
size_t predicted_class_top1 = indices[0];
282-
if (predicted_class_top1 == static_cast<size_t>(true_label)) {
283-
correct_predictions_top1++;
284-
}
285338

286-
bool found_in_top5 = false;
287-
for (int top_k = 0; top_k < std::min(5, static_cast<int>(indices.size()));
288-
++top_k) {
289-
if (indices[top_k] == static_cast<size_t>(true_label)) {
290-
found_in_top5 = true;
291-
break;
339+
LOG_MEM("Starting batch processing");
340+
auto total_start_time = std::chrono::high_resolution_clock::now();
341+
int total_inference_time = 0;
342+
343+
for (size_t batch_start = 0; batch_start < num_photo;
344+
batch_start += batch_size) {
345+
size_t batch_end = std::min(batch_start + batch_size, num_photo);
346+
size_t current_batch_size = batch_end - batch_start;
347+
348+
char batch_log[100];
349+
sprintf(batch_log, "Batch %zu/%zu (size %zu)", batch_start / batch_size + 1,
350+
(num_photo + batch_size - 1) / batch_size, current_batch_size);
351+
LOG_MEM(batch_log);
352+
353+
std::vector<float> batch_data;
354+
batch_data.reserve(current_batch_size * image_size);
355+
356+
size_t batch_offset = batch_start * image_size;
357+
batch_data.insert(batch_data.end(), all_image_data.begin() + batch_offset,
358+
all_image_data.begin() + batch_offset +
359+
current_batch_size * image_size);
360+
361+
it_lab_ai::Shape batch_input_shape(
362+
{current_batch_size, static_cast<size_t>(channels),
363+
static_cast<size_t>(height), static_cast<size_t>(width)});
364+
it_lab_ai::Tensor batch_input = make_tensor(batch_data, batch_input_shape);
365+
366+
it_lab_ai::Shape batch_output_shape({current_batch_size, output_classes});
367+
it_lab_ai::Tensor batch_output(batch_output_shape, it_lab_ai::Type::kFloat);
368+
369+
Graph graph;
370+
build_graph(graph, batch_input, batch_output, json_path, options, false);
371+
372+
LOG_MEM("Batch inference");
373+
// auto batch_start_time =
374+
// std::chrono::high_resolution_clock::now();
375+
graph.inference(options);
376+
total_inference_time += print_time_stats(graph);
377+
// auto batch_end_time = std::chrono::high_resolution_clock::now();
378+
// int batch_time =
379+
// static_cast<int>(std::chrono::duration_cast<std::chrono::milliseconds>(
380+
// batch_end_time - batch_start_time)
381+
// .count()); // ← Добавлен static_cast
382+
// total_inference_time += batch_time;
383+
// batch_count++;
384+
385+
// #ifdef ENABLE_STATISTIC_TIME
386+
// std::vector<int> elps_time = graph.getTime();
387+
// int batch_time = std::accumulate(elps_time.begin(),
388+
// elps_time.end(), 0); total_inference_time += batch_time;
389+
// batch_count++;
390+
//
391+
// char time_log[100];
392+
// sprintf(time_log, "Batch %d time: %d ms", batch_count,
393+
// batch_time); LOG_MEM(time_log);
394+
// #endif
395+
396+
const std::vector<float>& raw_batch_output = *batch_output.as<float>();
397+
398+
for (size_t i = 0; i < current_batch_size; ++i) {
399+
size_t global_idx = batch_start + i;
400+
401+
std::vector<float> single_output(
402+
raw_batch_output.begin() + i * output_classes,
403+
raw_batch_output.begin() + (i + 1) * output_classes);
404+
405+
float max_val =
406+
*std::max_element(single_output.begin(), single_output.end());
407+
float sum = 0.0f;
408+
for (float& val : single_output) {
409+
val = exp(val - max_val);
410+
sum += val;
411+
}
412+
for (float& val : single_output) {
413+
val /= sum;
414+
}
415+
416+
std::vector<size_t> indices(single_output.size());
417+
std::iota(indices.begin(), indices.end(), 0);
418+
std::sort(indices.begin(), indices.end(), [&](size_t a, size_t b) {
419+
return single_output[a] > single_output[b];
420+
});
421+
422+
if (indices[0] == static_cast<size_t>(true_labels[global_idx])) {
423+
correct_predictions_top1++;
424+
}
425+
426+
for (int top_k = 0; top_k < std::min(5, static_cast<int>(indices.size()));
427+
++top_k) {
428+
if (indices[top_k] == static_cast<size_t>(true_labels[global_idx])) {
429+
correct_predictions_top5++;
430+
break;
431+
}
292432
}
293433
}
294-
if (found_in_top5) {
295-
correct_predictions_top5++;
296-
}
434+
435+
batch_data.clear();
436+
batch_data.shrink_to_fit();
297437
}
298438

439+
auto total_end_time = std::chrono::high_resolution_clock::now();
440+
int total_time =
441+
static_cast<int>(std::chrono::duration_cast<std::chrono::milliseconds>(
442+
total_end_time - total_start_time)
443+
.count());
444+
445+
std::cout << "\n!INFERENCE TIME INFO START!" << '\n';
446+
std::cout << "Total inference time (sum of batches): " << total_inference_time
447+
<< " ms\n";
448+
std::cout << "Total wall-clock time for all batches: " << total_time
449+
<< " ms\n";
450+
std::cout << "Number of batches: " << batch_count << '\n';
451+
std::cout << "Average time per batch: "
452+
<< (batch_count > 0 ? total_inference_time / batch_count : 0)
453+
<< " ms\n";
454+
std::cout << "!INFERENCE TIME INFO END!" << '\n';
455+
/*std::cout << "\n!INFERENCE TIME INFO START!" << '\n';
456+
std::cout << "Total inference time for all batches: " << total_inference_time
457+
<< " ms\n";
458+
std::cout << "Number of batches: " << batch_count << '\n';
459+
std::cout << "!INFERENCE TIME INFO END!" << '\n';
460+
LOG_MEM("All batches processed");*/
461+
299462
double final_accuracy_top1 =
300463
(static_cast<double>(correct_predictions_top1) / num_photo) * 100;
301464
double final_accuracy_top5 =
@@ -305,6 +468,7 @@ int main(int argc, char* argv[]) {
305468
std::cout << "Model: " << model_name << '\n';
306469
std::cout << "Dataset: " << dataset_path << '\n';
307470
std::cout << "Total images: " << num_photo << '\n';
471+
std::cout << "Batch size: " << batch_size << '\n';
308472
std::cout << "Correct predictions (Top-1): " << correct_predictions_top1
309473
<< '\n';
310474
std::cout << "Correct predictions (Top-5): " << correct_predictions_top5
@@ -314,5 +478,13 @@ int main(int argc, char* argv[]) {
314478
std::cout << "Top-5 Accuracy: " << std::fixed << std::setprecision(2)
315479
<< final_accuracy_top5 << "%" << '\n';
316480

481+
all_image_data.clear();
482+
all_image_data.shrink_to_fit();
483+
image_paths.clear();
484+
image_paths.shrink_to_fit();
485+
true_labels.clear();
486+
true_labels.shrink_to_fit();
487+
488+
LOG_MEM("Program end");
317489
return 0;
318490
}

0 commit comments

Comments
 (0)