You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

test_fast_math.cpp 7.1 kB

11 months ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. // Copyright 2021 Tencent
  2. // SPDX-License-Identifier: BSD-3-Clause
  3. #include "datareader.h"
  4. #include "gpu.h"
  5. #include "mat.h"
  6. #include "net.h"
  7. #include "testutil.h"
  8. #include "benchmark.h" // For ncnn::get_current_time()
  9. #include <cstdio>
  10. #include <vector>
  11. #include <cstring> // For memset
  12. int device_index = 0;
  13. // A data reader that provides zero-filled data, useful for loading models without actual weights.
  14. class DataReaderFromEmpty : public ncnn::DataReader
  15. {
  16. public:
  17. virtual int scan(const char* format, void* p) const
  18. {
  19. (void)format; // unused
  20. (void)p; // unused
  21. return 0;
  22. }
  23. virtual size_t read(void* buf, size_t size) const
  24. {
  25. memset(buf, 0, size);
  26. return size;
  27. }
  28. };
  29. // The main test function to compare default vs. fast math performance.
  30. static int test_vulkan_fast_math()
  31. {
  32. // Define model path based on environment
  33. // Create a random input matrix
  34. ncnn::Mat input = RandomMat(224, 224, 3);
  35. DataReaderFromEmpty dr;
  36. #ifdef __EMSCRIPTEN__
  37. #define MODEL_DIR "/working"
  38. #else
  39. #define MODEL_DIR "../../benchmark"
  40. #endif
  41. // ==================================================
  42. // 1. Setup Net with Default Options
  43. // ==================================================
  44. printf("==================================================\n");
  45. printf(" Testing with Default Vulkan Options \n");
  46. printf("==================================================\n");
  47. ncnn::Net net_default;
  48. net_default.opt.use_vulkan_compute = true;
  49. net_default.opt.vulkan_device_index = device_index;
  50. net_default.opt.use_fp16_arithmetic = false;
  51. net_default.opt.use_fp16_storage = false;
  52. net_default.opt.use_fp16_packed = false;
  53. net_default.load_param(MODEL_DIR "/resnet50.param");
  54. net_default.load_model(dr);
  55. printf("Default net loaded successfully.\n");
  56. // ==================================================
  57. // 2. Setup Net with Fast Math Options
  58. // ==================================================
  59. printf("\n==================================================\n");
  60. printf(" Testing with Vulkan Fast Math Options \n");
  61. printf("==================================================\n");
  62. ncnn::Net net_fast_math;
  63. net_fast_math.opt.use_vulkan_compute = true;
  64. net_fast_math.opt.vk_fast_math_flag = ncnn::Option::VK_FAST_MATH_FLAG_AllowContract;
  65. net_fast_math.opt.vulkan_device_index = device_index;
  66. net_fast_math.opt.use_fp16_arithmetic = false;
  67. net_fast_math.opt.use_fp16_packed = false;
  68. net_fast_math.opt.use_fp16_storage = false;
  69. net_fast_math.load_param(MODEL_DIR "/resnet50.param");
  70. net_fast_math.load_model(dr);
  71. printf("Fast math net loaded successfully.\n");
  72. // ==================================================
  73. // 3. Warm-up Run
  74. // ==================================================
  75. printf("\n==================================================\n");
  76. printf(" Warming up both networks... \n");
  77. printf("==================================================\n");
  78. ncnn::Mat output_default, output_fast_math;
  79. {
  80. ncnn::Extractor ex = net_default.create_extractor();
  81. ex.input("data", input);
  82. ex.extract("output", output_default);
  83. }
  84. {
  85. ncnn::Extractor ex = net_fast_math.create_extractor();
  86. ex.input("data", input);
  87. ex.extract("output", output_fast_math);
  88. }
  89. printf("Warm-up complete.\n");
  90. // ==================================================
  91. // 4. Benchmark Performance
  92. // ==================================================
  93. printf("\n==================================================\n");
  94. printf(" Benchmarking Performance \n");
  95. printf("==================================================\n");
  96. const int loop_count = 10;
  97. double time_default = 0;
  98. double time_fast_math = 0;
  99. // Benchmark default net
  100. {
  101. double start = ncnn::get_current_time();
  102. for (int i = 0; i < loop_count; i++)
  103. {
  104. ncnn::Extractor ex = net_default.create_extractor();
  105. ex.input("data", input);
  106. ex.extract("output", output_default);
  107. }
  108. double end = ncnn::get_current_time();
  109. time_default = (end - start) / loop_count;
  110. printf("Default Net Average Time: %.2f ms\n", time_default);
  111. }
  112. // Benchmark fast math net
  113. {
  114. double start = ncnn::get_current_time();
  115. for (int i = 0; i < loop_count; i++)
  116. {
  117. ncnn::Extractor ex = net_fast_math.create_extractor();
  118. ex.input("data", input);
  119. ex.extract("output", output_fast_math);
  120. }
  121. double end = ncnn::get_current_time();
  122. time_fast_math = (end - start) / loop_count;
  123. printf("Fast Math Net Average Time: %.2f ms\n", time_fast_math);
  124. }
  125. // ==================================================
  126. // 5. Verification and Summary
  127. // ==================================================
  128. printf("\n==================================================\n");
  129. printf(" Verification and Summary \n");
  130. printf("==================================================\n");
  131. // Compare results. A larger tolerance is needed due to fast math optimizations.
  132. int ret = CompareMat(output_default, output_fast_math, 0.01f);
  133. printf("Output comparison result (0 means success): %d\n", ret);
  134. if (ret != 0)
  135. {
  136. fprintf(stderr, "Warning: Output mismatch is larger than tolerance. Fast math might be affecting precision significantly.\n");
  137. }
  138. else
  139. {
  140. printf("Output verification: SUCCESS (within tolerance)\n");
  141. }
  142. printf("--------------------------------------------------\n");
  143. printf("Performance Summary:\n");
  144. printf(" - Default Net: %.2f ms\n", time_default);
  145. printf(" - Fast Math Net: %.2f ms\n", time_fast_math);
  146. if (time_default > 0 && time_fast_math > 0)
  147. {
  148. double speedup = (time_default - time_fast_math) / time_default * 100;
  149. printf(" - Speedup: %.2f%%\n", speedup);
  150. }
  151. printf("\nTest finished.\n");
  152. return 0;
  153. }
  154. int main(int argc, char** argv)
  155. {
  156. if (argc >= 2)
  157. {
  158. device_index = atoi(argv[1]);
  159. }
  160. int gpu_count = ncnn::get_gpu_count();
  161. if (device_index < 0 || device_index >= gpu_count)
  162. {
  163. fprintf(stderr, "Invalid GPU device index %d. The valid range is [0, %d-1]. Using default device 0.\n", device_index, gpu_count);
  164. device_index = 0;
  165. }
  166. if (!ncnn::get_gpu_device(device_index)->info.support_VK_KHR_shader_float_controls2())
  167. {
  168. fprintf(stderr, "The selected device does not support VK_KHR_shader_float_controls2. Fast math tests may not be valid.\n");
  169. return 0;
  170. }
  171. // Set the default device for all ncnn operations.
  172. printf("Using Vulkan Device: %d\n", device_index);
  173. // Run the performance test.
  174. int ret = test_vulkan_fast_math();
  175. return ret;
  176. }