source: trunk/test/lol-bench.cpp @ 886

Last change on this file since 886 was 886, checked in by sam, 11 years ago

test: add benchmark tests for trigonometry functions.

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