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

336 lines
9.7 KiB

  1. //
  2. // Lol Engine - Benchmark program
  3. //
  4. // Copyright: (c) 2005-2011 Sam Hocevar <sam@hocevar.net>
  5. // This program is free software; you can redistribute it and/or
  6. // modify it under the terms of the Do What The Fuck You Want To
  7. // Public License, Version 2, as published by Sam Hocevar. See
  8. // http://sam.zoy.org/projects/COPYING.WTFPL for more details.
  9. //
  10. #if defined HAVE_CONFIG_H
  11. # include "config.h"
  12. #endif
  13. #include <cstdio>
  14. #if defined HAVE_FASTMATH_H
  15. # include <fastmath.h>
  16. #endif
  17. #include "core.h"
  18. #include "loldebug.h"
  19. using namespace std;
  20. using namespace lol;
  21. static size_t const TRIG_TABLE_SIZE = 128 * 1024;
  22. static size_t const TRIG_RUNS = 50;
  23. static size_t const MATRIX_TABLE_SIZE = 64 * 1024;
  24. static size_t const MATRIX_RUNS = 100;
  25. static size_t const HALF_TABLE_SIZE = 1024 * 1024;
  26. static size_t const HALF_RUNS = 50;
  27. static void bench_trig(int mode);
  28. static void bench_matrix(int mode);
  29. static void bench_half(int mode);
  30. int main(int argc, char **argv)
  31. {
  32. Log::Info("--------------------------\n");
  33. Log::Info(" Trigonometry [-1e5, 1e5]\n");
  34. Log::Info("--------------------------\n");
  35. bench_trig(1);
  36. Log::Info("------------------------\n");
  37. Log::Info(" Trigonometry [-pi, pi]\n");
  38. Log::Info("------------------------\n");
  39. bench_trig(2);
  40. Log::Info("----------------------------\n");
  41. Log::Info(" Trigonometry [-1e-2, 1e-2]\n");
  42. Log::Info("----------------------------\n");
  43. bench_trig(3);
  44. Log::Info("----------------------------\n");
  45. Log::Info(" Float matrices [-2.0, 2.0]\n");
  46. Log::Info("----------------------------\n");
  47. bench_matrix(1);
  48. Log::Info("-------------------------------------\n");
  49. Log::Info(" Half precision floats (random bits)\n");
  50. Log::Info("-------------------------------------\n");
  51. bench_half(1);
  52. Log::Info("-----------------------------------\n");
  53. Log::Info(" Half precision floats [-2.0, 2.0]\n");
  54. Log::Info("-----------------------------------\n");
  55. bench_half(2);
  56. return EXIT_SUCCESS;
  57. }
  58. static void bench_trig(int mode)
  59. {
  60. float result[7] = { 0.0f };
  61. Timer timer;
  62. /* Set up tables */
  63. float *pf = new float[TRIG_TABLE_SIZE];
  64. float *pf2 = new float[TRIG_TABLE_SIZE];
  65. for (size_t run = 0; run < TRIG_RUNS; run++)
  66. {
  67. switch (mode)
  68. {
  69. case 1:
  70. for (size_t i = 0; i < TRIG_TABLE_SIZE; i++)
  71. pf[i] = RandF(-1e5f, 1e5f);
  72. break;
  73. case 2:
  74. for (size_t i = 0; i < TRIG_TABLE_SIZE; i++)
  75. pf[i] = RandF(-M_PI, M_PI);
  76. break;
  77. case 3:
  78. for (size_t i = 0; i < TRIG_TABLE_SIZE; i++)
  79. pf[i] = RandF(-1e-2f, 1e-2f);
  80. break;
  81. }
  82. /* Sin */
  83. timer.GetMs();
  84. for (size_t i = 0; i < TRIG_TABLE_SIZE; i++)
  85. pf2[i] = __builtin_sinf(pf[i]);
  86. result[0] += timer.GetMs();
  87. /* Fast sin */
  88. timer.GetMs();
  89. for (size_t i = 0; i < TRIG_TABLE_SIZE; i++)
  90. #if defined HAVE_FASTMATH_H
  91. pf2[i] = f_sinf(pf[i]);
  92. #else
  93. pf2[i] = sinf(pf[i]);
  94. #endif
  95. result[1] += timer.GetMs();
  96. /* Lol sin */
  97. timer.GetMs();
  98. for (size_t i = 0; i < TRIG_TABLE_SIZE; i++)
  99. pf2[i] = lol_sin(pf[i]);
  100. result[2] += timer.GetMs();
  101. /* Cos */
  102. timer.GetMs();
  103. for (size_t i = 0; i < TRIG_TABLE_SIZE; i++)
  104. pf2[i] = __builtin_cosf(pf[i]);
  105. result[3] += timer.GetMs();
  106. /* Fast cos */
  107. timer.GetMs();
  108. for (size_t i = 0; i < TRIG_TABLE_SIZE; i++)
  109. #if defined HAVE_FASTMATH_H
  110. pf2[i] = f_cosf(pf[i]);
  111. #else
  112. pf2[i] = cosf(pf[i]);
  113. #endif
  114. result[4] += timer.GetMs();
  115. /* Lol cos */
  116. timer.GetMs();
  117. for (size_t i = 0; i < TRIG_TABLE_SIZE; i++)
  118. pf2[i] = lol_cos(pf[i]);
  119. result[5] += timer.GetMs();
  120. /* Tan */
  121. timer.GetMs();
  122. for (size_t i = 0; i < TRIG_TABLE_SIZE; i++)
  123. pf2[i] = __builtin_tanf(pf[i]);
  124. result[6] += timer.GetMs();
  125. }
  126. delete[] pf;
  127. delete[] pf2;
  128. for (size_t i = 0; i < sizeof(result) / sizeof(*result); i++)
  129. result[i] *= 1000000.0f / (TRIG_TABLE_SIZE * TRIG_RUNS);
  130. Log::Info(" ns/elem\n");
  131. Log::Info("float = sinf(float) %7.3f\n", result[0]);
  132. Log::Info("float = fastsinf(float) %7.3f\n", result[1]);
  133. Log::Info("float = lol_sinf(float) %7.3f\n", result[2]);
  134. Log::Info("float = cosf(float) %7.3f\n", result[3]);
  135. Log::Info("float = fastcosf(float) %7.3f\n", result[4]);
  136. Log::Info("float = lol_cosf(float) %7.3f\n", result[5]);
  137. Log::Info("float = tanf(float) %7.3f\n", result[6]);
  138. }
  139. static void bench_matrix(int mode)
  140. {
  141. float result[5] = { 0.0f };
  142. Timer timer;
  143. /* Set up tables */
  144. mat4 *pm = new mat4[MATRIX_TABLE_SIZE + 1];
  145. float *pf = new float[MATRIX_TABLE_SIZE];
  146. for (size_t run = 0; run < MATRIX_RUNS; run++)
  147. {
  148. switch (mode)
  149. {
  150. case 1:
  151. for (size_t i = 0; i < MATRIX_TABLE_SIZE; i++)
  152. for (int j = 0; j < 4; j++)
  153. for (int k = 0; k < 4; k++)
  154. pm[i][j][k] = RandF(-2.0f, 2.0f);
  155. break;
  156. }
  157. /* Copy matrices */
  158. timer.GetMs();
  159. for (size_t i = 0; i < MATRIX_TABLE_SIZE; i++)
  160. pm[i] = pm[i + 1];
  161. result[0] += timer.GetMs();
  162. /* Determinant */
  163. timer.GetMs();
  164. for (size_t i = 0; i < MATRIX_TABLE_SIZE; i++)
  165. pf[i] = pm[i].det();
  166. result[1] += timer.GetMs();
  167. /* Multiply matrices */
  168. timer.GetMs();
  169. for (size_t i = 0; i < MATRIX_TABLE_SIZE; i++)
  170. pm[i] *= pm[i + 1];
  171. result[2] += timer.GetMs();
  172. /* Add matrices */
  173. timer.GetMs();
  174. for (size_t i = 0; i < MATRIX_TABLE_SIZE; i++)
  175. pm[i] += pm[i + 1];
  176. result[3] += timer.GetMs();
  177. /* Invert matrix */
  178. timer.GetMs();
  179. for (size_t i = 0; i < MATRIX_TABLE_SIZE; i++)
  180. pm[i] = pm[i].invert();
  181. result[4] += timer.GetMs();
  182. }
  183. delete[] pm;
  184. delete[] pf;
  185. for (size_t i = 0; i < sizeof(result) / sizeof(*result); i++)
  186. result[i] *= 1000000.0f / (MATRIX_TABLE_SIZE * MATRIX_RUNS);
  187. Log::Info(" ns/elem\n");
  188. Log::Info("mat4 = mat4 %7.3f\n", result[0]);
  189. Log::Info("float = mat4.det() %7.3f\n", result[1]);
  190. Log::Info("mat4 *= mat4 %7.3f\n", result[2]);
  191. Log::Info("mat4 += mat4 %7.3f\n", result[3]);
  192. Log::Info("mat4 = mat4.invert() %7.3f\n", result[4]);
  193. }
  194. static void bench_half(int mode)
  195. {
  196. float result[10] = { 0.0f };
  197. Timer timer;
  198. /* Set up tables */
  199. float *pf = new float[HALF_TABLE_SIZE + 1];
  200. half *ph = new half[HALF_TABLE_SIZE + 1];
  201. for (size_t run = 0; run < HALF_RUNS; run++)
  202. {
  203. switch (mode)
  204. {
  205. case 1:
  206. for (size_t i = 0; i < HALF_TABLE_SIZE + 1; i++)
  207. ph[i] = half::makebits(rand());
  208. break;
  209. case 2:
  210. for (size_t i = 0; i < HALF_TABLE_SIZE + 1; i++)
  211. ph[i] = RandF(-2.0f, 2.0f);
  212. break;
  213. }
  214. /* Copy float */
  215. timer.GetMs();
  216. for (size_t i = 0; i < HALF_TABLE_SIZE; i++)
  217. pf[i] = pf[i + 1];
  218. result[0] += timer.GetMs();
  219. /* Convert half to float (array) */
  220. timer.GetMs();
  221. half::convert(pf, ph, HALF_TABLE_SIZE);
  222. result[1] += timer.GetMs();
  223. /* Convert half to float (fast) */
  224. timer.GetMs();
  225. for (size_t i = 0; i < HALF_TABLE_SIZE; i++)
  226. pf[i] = (float)ph[i];
  227. result[2] += timer.GetMs();
  228. /* Add a half to every float */
  229. timer.GetMs();
  230. for (size_t i = 0; i < HALF_TABLE_SIZE; i++)
  231. pf[i] += ph[i];
  232. result[3] += timer.GetMs();
  233. /* Copy half */
  234. timer.GetMs();
  235. for (size_t i = 0; i < HALF_TABLE_SIZE; i++)
  236. ph[i] = ph[i + 1];
  237. result[4] += timer.GetMs();
  238. /* Change sign of every half */
  239. timer.GetMs();
  240. for (size_t i = 0; i < HALF_TABLE_SIZE; i++)
  241. ph[i] = -ph[i];
  242. result[5] += timer.GetMs();
  243. /* Convert float to half (array) */
  244. timer.GetMs();
  245. half::convert(ph, pf, HALF_TABLE_SIZE);
  246. result[6] += timer.GetMs();
  247. /* Convert float to half (fast) */
  248. timer.GetMs();
  249. for (size_t i = 0; i < HALF_TABLE_SIZE; i++)
  250. ph[i] = (half)pf[i];
  251. result[7] += timer.GetMs();
  252. /* Convert float to half (accurate) */
  253. timer.GetMs();
  254. for (size_t i = 0; i < HALF_TABLE_SIZE; i++)
  255. ph[i] = half::makeaccurate(pf[i]);
  256. result[8] += timer.GetMs();
  257. /* Add a float to every half */
  258. timer.GetMs();
  259. for (size_t i = 0; i < HALF_TABLE_SIZE; i++)
  260. ph[i] += pf[i];
  261. result[9] += timer.GetMs();
  262. }
  263. delete[] pf;
  264. delete[] ph;
  265. for (size_t i = 0; i < sizeof(result) / sizeof(*result); i++)
  266. result[i] *= 1000000.0f / (HALF_TABLE_SIZE * HALF_RUNS);
  267. Log::Info(" ns/elem\n");
  268. Log::Info("float = float %7.3f\n", result[0]);
  269. Log::Info("float = half (array) %7.3f\n", result[1]);
  270. Log::Info("float = half (fast) %7.3f\n", result[2]);
  271. Log::Info("float += half %7.3f\n", result[3]);
  272. Log::Info("half = half %7.3f\n", result[4]);
  273. Log::Info("half = -half %7.3f\n", result[5]);
  274. Log::Info("half = float (array) %7.3f\n", result[6]);
  275. Log::Info("half = float (fast) %7.3f\n", result[7]);
  276. Log::Info("half = float (accurate) %7.3f\n", result[8]);
  277. Log::Info("half += float %7.3f\n", result[9]);
  278. }