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.6 kB

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