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 8.3 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  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. static const char* mish25_param = R"delimiter(
  30. 7767517
  31. 26 26
  32. Input in0 0 1 in0
  33. Mish mish_0 1 1 in0 1
  34. Mish mish_1 1 1 1 2
  35. Mish mish_2 1 1 2 3
  36. Mish mish_3 1 1 3 4
  37. Mish mish_4 1 1 4 5
  38. Mish mish_5 1 1 5 6
  39. Mish mish_6 1 1 6 7
  40. Mish mish_7 1 1 7 8
  41. Mish mish_8 1 1 8 9
  42. Mish mish_9 1 1 9 10
  43. Mish mish_10 1 1 10 11
  44. Mish mish_11 1 1 11 12
  45. Mish mish_12 1 1 12 13
  46. Mish mish_13 1 1 13 14
  47. Mish mish_14 1 1 14 15
  48. Mish mish_15 1 1 15 16
  49. Mish mish_16 1 1 16 17
  50. Mish mish_17 1 1 17 18
  51. Mish mish_18 1 1 18 19
  52. Mish mish_19 1 1 19 20
  53. Mish mish_20 1 1 20 21
  54. Mish mish_21 1 1 21 22
  55. Mish mish_22 1 1 22 23
  56. Mish mish_23 1 1 23 24
  57. Mish mish_24 1 1 24 out0
  58. )delimiter";
  59. // The main test function to compare default vs. fast math performance.
  60. static int test_vulkan_fast_math()
  61. {
  62. // Define model path based on environment
  63. // Create a random input matrix
  64. ncnn::Mat input = RandomMat(512, 512, 3);
  65. DataReaderFromEmpty dr;
  66. // ==================================================
  67. // 1. Setup Net with Default Options
  68. // ==================================================
  69. printf("==================================================\n");
  70. printf(" Testing with Default Vulkan Options \n");
  71. printf("==================================================\n");
  72. ncnn::Net net_default;
  73. net_default.opt.use_vulkan_compute = true;
  74. net_default.opt.vulkan_device_index = device_index;
  75. net_default.load_param_mem(mish25_param);
  76. net_default.load_model(dr);
  77. printf("Default net loaded successfully.\n");
  78. // ==================================================
  79. // 2. Setup Net with Fast Math Options
  80. // ==================================================
  81. printf("\n==================================================\n");
  82. printf(" Testing with Vulkan Fast Math Options \n");
  83. printf("==================================================\n");
  84. ncnn::Net net_fast_math;
  85. net_fast_math.opt.use_vulkan_compute = true;
  86. net_fast_math.opt.vk_fast_math_flag = ncnn::Option::VK_FAST_MATH_FLAG_Fast
  87. | ncnn::Option::VK_FAST_MATH_FLAG_AllowContract
  88. | ncnn::Option::VK_FAST_MATH_FLAG_AllowReassoc
  89. | ncnn::Option::VK_FAST_MATH_FLAG_AllowTransform;
  90. net_fast_math.opt.vulkan_device_index = device_index;
  91. net_fast_math.load_param_mem(mish25_param);
  92. net_fast_math.load_model(dr);
  93. printf("Fast math net loaded successfully.\n");
  94. // ==================================================
  95. // 3. Warm-up Run
  96. // ==================================================
  97. printf("\n==================================================\n");
  98. printf(" Warming up both networks... \n");
  99. printf("==================================================\n");
  100. ncnn::Mat output_default, output_fast_math;
  101. {
  102. ncnn::Extractor ex = net_default.create_extractor();
  103. ex.input("in0", input);
  104. ex.extract("out0", output_default);
  105. }
  106. {
  107. ncnn::Extractor ex = net_fast_math.create_extractor();
  108. ex.input("in0", input);
  109. ex.extract("out0", output_fast_math);
  110. }
  111. printf("Warm-up complete.\n");
  112. // ==================================================
  113. // 4. Benchmark Performance
  114. // ==================================================
  115. printf("\n==================================================\n");
  116. printf(" Benchmarking Performance \n");
  117. printf("==================================================\n");
  118. const int loop_count = 10;
  119. double time_default = 0;
  120. double time_fast_math = 0;
  121. // Benchmark default net
  122. {
  123. double start = ncnn::get_current_time();
  124. for (int i = 0; i < loop_count; i++)
  125. {
  126. ncnn::Extractor ex = net_default.create_extractor();
  127. ex.input("in0", input);
  128. ex.extract("out0", output_default);
  129. }
  130. double end = ncnn::get_current_time();
  131. time_default = (end - start) / loop_count;
  132. printf("Default Net Average Time: %.2f ms\n", time_default);
  133. }
  134. // Benchmark fast math net
  135. {
  136. double start = ncnn::get_current_time();
  137. for (int i = 0; i < loop_count; i++)
  138. {
  139. ncnn::Extractor ex = net_fast_math.create_extractor();
  140. ex.input("in0", input);
  141. ex.extract("out0", output_fast_math);
  142. }
  143. double end = ncnn::get_current_time();
  144. time_fast_math = (end - start) / loop_count;
  145. printf("Fast Math Net Average Time: %.2f ms\n", time_fast_math);
  146. }
  147. // ==================================================
  148. // 5. Verification and Summary
  149. // ==================================================
  150. printf("\n==================================================\n");
  151. printf(" Verification and Summary \n");
  152. printf("==================================================\n");
  153. // Compare results. A larger tolerance is needed due to fast math optimizations.
  154. int ret = CompareMat(output_default, output_fast_math, 0.01f);
  155. printf("Output comparison result (0 means success): %d\n", ret);
  156. if (ret != 0)
  157. {
  158. fprintf(stderr, "Warning: Output mismatch is larger than tolerance. Fast math might be affecting precision significantly.\n");
  159. }
  160. else
  161. {
  162. printf("Output verification: SUCCESS (within tolerance)\n");
  163. }
  164. printf("--------------------------------------------------\n");
  165. printf("Performance Summary:\n");
  166. printf(" - Default Net: %.2f ms\n", time_default);
  167. printf(" - Fast Math Net: %.2f ms\n", time_fast_math);
  168. if (time_default > 0 && time_fast_math > 0)
  169. {
  170. double speedup = (time_default - time_fast_math) / time_default * 100;
  171. printf(" - Speedup: %.2f%%\n", speedup);
  172. }
  173. printf("\nTest finished.\n");
  174. return 0;
  175. }
  176. int main(int argc, char** argv)
  177. {
  178. if (argc >= 2)
  179. {
  180. device_index = atoi(argv[1]);
  181. }
  182. int gpu_count = ncnn::get_gpu_count();
  183. if (device_index < 0 || device_index >= gpu_count)
  184. {
  185. fprintf(stderr, "Invalid GPU device index %d. The valid range is [0, %d-1]. Using default device 0.\n", device_index, gpu_count);
  186. device_index = 0;
  187. }
  188. // Set the default device for all ncnn operations.
  189. printf("Using Vulkan Device: %d\n", device_index);
  190. // Run the performance test.
  191. int ret = test_vulkan_fast_math();
  192. return ret;
  193. }