Refactoring of rec process "~" in faustexp.ml.
[Faustine.git] / interpretor / faust-0.9.47mr3 / architecture / bench.cpp
1 /************************************************************************
2
3 IMPORTANT NOTE : this file contains two clearly delimited sections :
4 the ARCHITECTURE section (in two parts) and the USER section. Each section
5 is governed by its own copyright and license. Please check individually
6 each section for license and copyright information.
7 *************************************************************************/
8
9 /*******************BEGIN ARCHITECTURE SECTION (part 1/2)****************/
10
11 /************************************************************************
12 FAUST Architecture File
13 Copyright (C) 2003-2011 GRAME, Centre National de Creation Musicale
14 ---------------------------------------------------------------------
15 This Architecture section is free software; you can redistribute it
16 and/or modify it under the terms of the GNU General Public License
17 as published by the Free Software Foundation; either version 3 of
18 the License, or (at your option) any later version.
19
20 This program is distributed in the hope that it will be useful,
21 but WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 GNU General Public License for more details.
24
25 You should have received a copy of the GNU General Public License
26 along with this program; If not, see <http://www.gnu.org/licenses/>.
27
28 EXCEPTION : As a special exception, you may create a larger work
29 that contains this FAUST architecture section and distribute
30 that work under terms of your choice, so long as this FAUST
31 architecture section is not modified.
32
33
34 ************************************************************************
35 ************************************************************************/
36
37
38 /* link with */
39 /* link with : "" */
40 #include <stdlib.h>
41 #include <stdlib.h>
42 #include <stdio.h>
43 #include <string.h>
44 #include <limits.h>
45 #include <math.h>
46 #include <errno.h>
47 #include <time.h>
48 #include <sys/ioctl.h>
49 #include <unistd.h>
50 #include <fcntl.h>
51 #include <pwd.h>
52 #include <sys/types.h>
53 #include <assert.h>
54 #include <pthread.h>
55 #include <sys/wait.h>
56 #include <list>
57
58 #include <iostream>
59
60
61 using namespace std;
62
63 #include <map>
64
65 using namespace std;
66
67 // On Intel set FZ (Flush to Zero) and DAZ (Denormals Are Zero)
68 // flags to avoid costly denormals
69 #ifdef __SSE__
70 #include <xmmintrin.h>
71 #ifdef __SSE2__
72 #define AVOIDDENORMALS _mm_setcsr(_mm_getcsr() | 0x8040)
73 #else
74 #define AVOIDDENORMALS _mm_setcsr(_mm_getcsr() | 0x8000)
75 #endif
76 #else
77 #define AVOIDDENORMALS
78 #endif
79
80 struct Meta : map<const char*, const char*>
81 {
82 void declare (const char* key, const char* value) { (*this)[key]=value; }
83 };
84
85
86
87 float* gBuffer = 0; // a buffer of NV*VSize samples
88
89 unsigned int COUNT = 2000; // number of measures
90 unsigned int NV = 4096; // number of vectors in BIG buffer (should exceed cache)
91 unsigned int ITER = 10; // number of iterations per measure
92 unsigned int VSIZE = 4096; // size of a vector in samples
93 unsigned int IDX = 0; // current vector number (0 <= VIdx < NV)
94
95
96 //inline void *aligned_calloc(size_t nmemb, size_t size) { return (void*)((unsigned)(calloc((nmemb*size)+15,sizeof(char)))+15 & 0xfffffff0); }
97 //inline void *aligned_calloc(size_t nmemb, size_t size) { return (void*)((size_t)(calloc((nmemb*size)+15,sizeof(char)))+15 & ~15); }
98
99
100
101 // g++ -Wall -O3 -lm -lpthread -lasound `gtk-config --cflags --libs` test.cpp -o test
102
103
104 //-------------------------------------------------------------------
105 // Generic min and max using c++ inline
106 //-------------------------------------------------------------------
107
108 inline int max (unsigned int a, unsigned int b) { return (a>b) ? a : b; }
109 inline int max (int a, int b) { return (a>b) ? a : b; }
110
111 inline long max (long a, long b) { return (a>b) ? a : b; }
112 inline long max (int a, long b) { return (a>b) ? a : b; }
113 inline long max (long a, int b) { return (a>b) ? a : b; }
114
115 inline float max (float a, float b) { return (a>b) ? a : b; }
116 inline float max (int a, float b) { return (a>b) ? a : b; }
117 inline float max (float a, int b) { return (a>b) ? a : b; }
118 inline float max (long a, float b) { return (a>b) ? a : b; }
119 inline float max (float a, long b) { return (a>b) ? a : b; }
120
121 inline double max (double a, double b) { return (a>b) ? a : b; }
122 inline double max (int a, double b) { return (a>b) ? a : b; }
123 inline double max (double a, int b) { return (a>b) ? a : b; }
124 inline double max (long a, double b) { return (a>b) ? a : b; }
125 inline double max (double a, long b) { return (a>b) ? a : b; }
126 inline double max (float a, double b) { return (a>b) ? a : b; }
127 inline double max (double a, float b) { return (a>b) ? a : b; }
128
129
130 inline int min (int a, int b) { return (a<b) ? a : b; }
131
132 inline long min (long a, long b) { return (a<b) ? a : b; }
133 inline long min (int a, long b) { return (a<b) ? a : b; }
134 inline long min (long a, int b) { return (a<b) ? a : b; }
135
136 inline float min (float a, float b) { return (a<b) ? a : b; }
137 inline float min (int a, float b) { return (a<b) ? a : b; }
138 inline float min (float a, int b) { return (a<b) ? a : b; }
139 inline float min (long a, float b) { return (a<b) ? a : b; }
140 inline float min (float a, long b) { return (a<b) ? a : b; }
141
142 inline double min (double a, double b) { return (a<b) ? a : b; }
143 inline double min (int a, double b) { return (a<b) ? a : b; }
144 inline double min (double a, int b) { return (a<b) ? a : b; }
145 inline double min (long a, double b) { return (a<b) ? a : b; }
146 inline double min (double a, long b) { return (a<b) ? a : b; }
147 inline double min (float a, double b) { return (a<b) ? a : b; }
148 inline double min (double a, float b) { return (a<b) ? a : b; }
149
150
151 inline int lsr (int x, int n) { return int(((unsigned int)x) >> n); }
152
153
154 bool setRealtimePriority ()
155 {
156 struct passwd * pw;
157 int err;
158 uid_t uid;
159 int policy;
160 struct sched_param param;
161
162 uid = getuid ();
163 pw = getpwnam ("root");
164 setuid (pw->pw_uid);
165
166 pthread_getschedparam(pthread_self(), &policy, &param);
167 policy = SCHED_RR;
168 param.sched_priority = 50;
169 err = pthread_setschedparam(pthread_self(), policy, &param);
170
171 setuid (uid);
172 return (err != -1);
173 }
174
175 #include <sys/time.h>
176
177 double mysecond()
178 {
179 struct timeval tp;
180 struct timezone tzp;
181 int i;
182
183 i = gettimeofday(&tp,&tzp);
184 return ( (double) tp.tv_sec + (double) tp.tv_usec * 1.e-6 );
185 }
186
187 /******************************************************************************
188 *******************************************************************************
189
190 VECTOR INTRINSICS
191
192 *******************************************************************************
193 *******************************************************************************/
194
195
196
197 <<includeIntrinsic>>
198
199
200
201 /******************************************************************************
202 *******************************************************************************
203
204 ABSTRACT USER INTERFACE
205
206 *******************************************************************************
207 *******************************************************************************/
208
209 class UI
210 {
211 bool fStopped;
212 public:
213
214 UI() : fStopped(false) {}
215 virtual ~UI() {}
216
217 virtual void addButton(const char* label, float* zone) = 0;
218 virtual void addToggleButton(const char* label, float* zone) = 0;
219 virtual void addCheckButton(const char* label, float* zone) = 0;
220 virtual void addVerticalSlider(const char* label, float* zone, float init, float min, float max, float step) = 0;
221 virtual void addHorizontalSlider(const char* label, float* zone, float init, float min, float max, float step) = 0;
222 virtual void addNumEntry(const char* label, float* zone, float init, float min, float max, float step) = 0;
223
224 // -- passive widgets
225
226 virtual void addNumDisplay(const char* label, float* zone, int precision) = 0;
227 virtual void addTextDisplay(const char* label, float* zone, char* names[], float min, float max) = 0;
228 virtual void addHorizontalBargraph(const char* label, float* zone, float min, float max) = 0;
229 virtual void addVerticalBargraph(const char* label, float* zone, float min, float max) = 0;
230
231 virtual void openFrameBox(const char* label) = 0;
232 virtual void openTabBox(const char* label) = 0;
233 virtual void openHorizontalBox(const char* label) = 0;
234 virtual void openVerticalBox(const char* label) = 0;
235
236 virtual void closeBox() = 0;
237
238 virtual void run() = 0;
239
240 void stop() { fStopped = true; }
241 bool stopped() { return fStopped; }
242
243 virtual void declare(float* zone, const char* key, const char* value) {}
244 };
245
246
247
248
249 /******************************************************************************
250 *******************************************************************************
251
252 DSP
253
254 *******************************************************************************
255 *******************************************************************************/
256
257
258
259 //----------------------------------------------------------------
260 // definition du processeur de signal
261 //----------------------------------------------------------------
262
263 class dsp {
264 protected:
265 int fSamplingFreq;
266 public:
267 dsp() {}
268 virtual ~dsp() {}
269 virtual int getNumInputs() = 0;
270 virtual int getNumOutputs() = 0;
271 virtual void buildUserInterface(UI* interface) = 0;
272 virtual void init(int samplingRate) = 0;
273 virtual void compute(int len, float** inputs, float** outputs) = 0;
274 };
275
276 /********************END ARCHITECTURE SECTION (part 1/2)****************/
277
278 /**************************BEGIN USER SECTION **************************/
279
280 <<includeclass>>
281
282 /***************************END USER SECTION ***************************/
283
284 /*******************BEGIN ARCHITECTURE SECTION (part 2/2)***************/
285
286 mydsp DSP;
287
288
289 #if 0
290
291 static __inline__ unsigned long long int rdtsc(void)
292 {
293 unsigned long long int x;
294 __asm__ volatile (".byte 0x0f, 0x31" : "=A" (x));
295 return x;
296 }
297
298 #endif
299
300 /**
301 * Bench by calling COUNT times the compute() method for
302 * the computation of vsize samples
303 */
304
305 #define MEGABYTE 1048576.0
306
307 void statistic(const char* name, double* timing)
308 {
309 double lo, hi, tot;
310 double mega = double(VSIZE*ITER)/MEGABYTE; // mega samples
311 // skip first 10 values to avoid cache bias ???
312 lo = hi = tot = mega/(timing[11] - timing[10]);
313 for (int i = 11; i<COUNT; i++) {
314 double delta = mega/(timing[i] - timing[i-1]);
315 if (delta < lo) {
316 lo = delta;
317 } else if (delta > hi) {
318 hi = delta;
319 }
320 tot += delta;
321 }
322
323 cout << '\t' << hi
324 << '\t' << hi*4*DSP.getNumInputs() << '\t' << "MB/s inputs"
325 << '\t' << hi*4*DSP.getNumOutputs() << '\t' << "MB/s outputs"
326 << '\t' << tot/(COUNT-11)
327 << '\t' << lo
328 << endl;
329 }
330
331 void allocBuffer()
332 {
333 unsigned int BSIZE = NV * VSIZE;
334 gBuffer = (float*) calloc (BSIZE, sizeof(float));
335
336 int R0_0 = 0;
337 for (int j = 0; j < BSIZE; j++) {
338 int R0temp0 = (12345 + (1103515245 * R0_0));
339 gBuffer[j] = 4.656613e-10f*R0temp0;
340 R0_0 = R0temp0;
341 }
342 }
343
344 float* nextVect()
345 {
346 IDX = (1+IDX)%NV;
347 return &gBuffer[IDX*VSIZE];
348 }
349
350 void bench(const char* name)
351 {
352
353 int numInChan = DSP.getNumInputs();
354 int numOutChan = DSP.getNumOutputs();
355
356 assert (numInChan < 256);
357 assert (numOutChan < 256);
358
359 float* inChannel[256];
360 float* outChannel[256];
361
362 // allocate input buffers (initialized with white noise)
363 allocBuffer();
364
365 // allocate output channels (not initialized)
366 for (int i = 0; i < numOutChan; i++) outChannel[i] = (float*) calloc (VSIZE, sizeof(float));
367
368 // init the dsp with a resoneable sampling rate)
369 DSP.init(48000);
370 double* timing = (double*) calloc (COUNT, sizeof(double));
371
372 for (int i = 0; i<COUNT; i++) {
373 timing[i] = mysecond();
374 for (int k = 0; k<ITER; k++) {
375 // allocate new input buffers to avoid L2 cache
376 for (int c=0; c<numInChan; c++) { inChannel[c] = nextVect(); }
377 DSP.compute(VSIZE,inChannel,outChannel);
378 }
379 }
380
381 statistic(name, timing);
382 }
383
384 //-------------------------------------------------------------------------
385 // MAIN
386 //-------------------------------------------------------------------------
387
388 // lopt : Scan Command Line long int Arguments
389
390 long lopt (int argc, char *argv[], const char* longname, const char* shortname, long def)
391 {
392 for (int i=2; i<argc; i++)
393 if ( strcmp(argv[i-1], shortname) == 0 || strcmp(argv[i-1], longname) == 0 )
394 return atoi(argv[i]);
395 return def;
396 }
397
398
399 int main(int argc, char *argv[] )
400 {
401 AVOIDDENORMALS;
402 VSIZE = lopt(argc, argv, "--vector-size", "-vec", 4096);
403 NV = lopt(argc, argv, "--num-vector", "-n", 20000);
404 COUNT = lopt(argc, argv, "--count", "-c", 1000);
405 ITER = lopt(argc, argv, "--iteration", "-i", 10);
406 //setRealtimePriority();
407 bench(argv[0]);
408 return 0;
409 }
410
411
412 /********************END ARCHITECTURE SECTION (part 2/2)****************/
413
414
415