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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  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 = 1;
  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(512, 512, 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_Fast
  65. | ncnn::Option::VK_FAST_MATH_FLAG_AllowContract
  66. | ncnn::Option::VK_FAST_MATH_FLAG_AllowReassoc
  67. | ncnn::Option::VK_FAST_MATH_FLAG_AllowTransform;
  68. net_fast_math.opt.vulkan_device_index = device_index;
  69. net_fast_math.opt.use_fp16_arithmetic = false;
  70. net_fast_math.opt.use_fp16_packed = false;
  71. net_fast_math.opt.use_fp16_storage = false;
  72. net_fast_math.load_param(MODEL_DIR "/resnet50.param");
  73. net_fast_math.load_model(dr);
  74. printf("Fast math net loaded successfully.\n");
  75. // ==================================================
  76. // 3. Warm-up Run
  77. // ==================================================
  78. printf("\n==================================================\n");
  79. printf(" Warming up both networks... \n");
  80. printf("==================================================\n");
  81. ncnn::Mat output_default, output_fast_math;
  82. {
  83. ncnn::Extractor ex = net_default.create_extractor();
  84. ex.input("data", input);
  85. ex.extract("output", output_default);
  86. }
  87. {
  88. ncnn::Extractor ex = net_fast_math.create_extractor();
  89. ex.input("data", input);
  90. ex.extract("output", output_fast_math);
  91. }
  92. printf("Warm-up complete.\n");
  93. // ==================================================
  94. // 4. Benchmark Performance
  95. // ==================================================
  96. printf("\n==================================================\n");
  97. printf(" Benchmarking Performance \n");
  98. printf("==================================================\n");
  99. const int loop_count = 10;
  100. double time_default = 0;
  101. double time_fast_math = 0;
  102. // Benchmark default net
  103. {
  104. double start = ncnn::get_current_time();
  105. for (int i = 0; i < loop_count; i++)
  106. {
  107. ncnn::Extractor ex = net_default.create_extractor();
  108. ex.input("data", input);
  109. ex.extract("output", output_default);
  110. }
  111. double end = ncnn::get_current_time();
  112. time_default = (end - start) / loop_count;
  113. printf("Default Net Average Time: %.2f ms\n", time_default);
  114. }
  115. // Benchmark fast math net
  116. {
  117. double start = ncnn::get_current_time();
  118. for (int i = 0; i < loop_count; i++)
  119. {
  120. ncnn::Extractor ex = net_fast_math.create_extractor();
  121. ex.input("data", input);
  122. ex.extract("output", output_fast_math);
  123. }
  124. double end = ncnn::get_current_time();
  125. time_fast_math = (end - start) / loop_count;
  126. printf("Fast Math Net Average Time: %.2f ms\n", time_fast_math);
  127. }
  128. // ==================================================
  129. // 5. Verification and Summary
  130. // ==================================================
  131. printf("\n==================================================\n");
  132. printf(" Verification and Summary \n");
  133. printf("==================================================\n");
  134. // Compare results. A larger tolerance is needed due to fast math optimizations.
  135. int ret = CompareMat(output_default, output_fast_math, 0.01f);
  136. printf("Output comparison result (0 means success): %d\n", ret);
  137. if (ret != 0)
  138. {
  139. fprintf(stderr, "Warning: Output mismatch is larger than tolerance. Fast math might be affecting precision significantly.\n");
  140. }
  141. else
  142. {
  143. printf("Output verification: SUCCESS (within tolerance)\n");
  144. }
  145. printf("--------------------------------------------------\n");
  146. printf("Performance Summary:\n");
  147. printf(" - Default Net: %.2f ms\n", time_default);
  148. printf(" - Fast Math Net: %.2f ms\n", time_fast_math);
  149. if (time_default > 0 && time_fast_math > 0)
  150. {
  151. double speedup = (time_default - time_fast_math) / time_default * 100;
  152. printf(" - Speedup: %.2f%%\n", speedup);
  153. }
  154. printf("\nTest finished.\n");
  155. return 0;
  156. }
  157. int main(int argc, char** argv)
  158. {
  159. if (argc >= 2)
  160. {
  161. device_index = atoi(argv[1]);
  162. }
  163. int gpu_count = ncnn::get_gpu_count();
  164. if (device_index < 0 || device_index >= gpu_count)
  165. {
  166. fprintf(stderr, "Invalid GPU device index %d. The valid range is [0, %d-1]. Using default device 0.\n", device_index, gpu_count);
  167. device_index = 0;
  168. }
  169. // Set the default device for all ncnn operations.
  170. printf("Using Vulkan Device: %d\n", device_index);
  171. // Run the performance test.
  172. int ret = test_vulkan_fast_math();
  173. return ret;
  174. }