source: trunk/lib_ir/AgnerTestP/PMCTest/PMCTestB64.nasm @ 4221

Last change on this file since 4221 was 4221, checked in by linmengl, 5 years ago

initial checkin of Agner Fog's performance script

File size: 14.6 KB
Line 
1;----------------------------------------------------------------------------
2;                        PMCTestB64.nasm              © 2013-08-20 Agner Fog
3;
4;                PMC Test program for multiple threads
5;                           NASM syntax
6;
7; This program is intended for testing the performance of a little piece of
8; code written in assembly language.
9; The code to test is inserted at the place marked "Test code start".
10; All sections that can be modified by the user are marked with ###########.
11;
12; The code to test will be executed REPETITIONS times and the test results
13; will be output for each repetition. This program measures how many clock
14; cycles the code to test takes in each repetition. Furthermore, it is
15; possible to set a number of Performance Monitor Counters (PMC) to count
16; the number of micro-operations (uops), cache misses, branch mispredictions,
17; etc.
18;
19; The setup of the Performance Monitor Counters is microprocessor-specific.
20; The specifications for PMC setup for each microprocessor family is defined
21; in the tables CounterDefinitions and CounterTypesDesired.
22;
23; See PMCTest.txt for instructions.
24;
25; (c) Copyright 2000 - 2013 by Agner Fog. GNU General Public License www.gnu.org/licenses
26;-----------------------------------------------------------------------------
27
28default rel
29
30; Operating system: 0 = Linux, 1 = Windows
31%ifndef WINDOWS
32%define  WINDOWS  0
33%endif
34
35; Define whether AVX and YMM registers used
36%ifndef  USEAVX
37%define  USEAVX   1
38%endif
39
40; Define cache line size (to avoid threads sharing cache lines):
41%define CACHELINESIZE  64
42
43; Define warmup count to get into max frequency state
44%define WARMUPCOUNT 10000000
45
46global TestLoop
47global CounterTypesDesired
48global NumThreads
49global MaxNumCounters
50global UsePMC
51global PThreadData
52global ThreadDataSize
53global ClockResultsOS
54global PMCResultsOS
55global ThreadData
56global NumCounters
57global Counters
58global EventRegistersUsed
59global UserData
60global RatioOut
61global TempOut
62global RatioOutTitle
63global TempOutTitle
64
65
66SECTION .data   align = CACHELINESIZE
67
68
69;##############################################################################
70;#
71;#            List of desired counter types and other user definitions
72;#
73;##############################################################################
74; Here you can select which performance monitor counters you want for your test.
75; Select id numbers from the table CounterDefinitions[] in PMCTestA.cpp.
76
77%define USE_PERFORMANCE_COUNTERS   1        ; Tell if you are using performance counters
78
79; Maximum number of PMC counters
80%define MAXCOUNTERS   6              ; must match value in PMCTest.h
81
82; Number of PMC counters
83%define NUM_COUNTERS  4              ; must match value in PMCTest.h
84
85CounterTypesDesired:
86 ;   DD      1        ; core cycles (Intel only)
87    DD      9        ; instructions
88    DD    100        ; uops
89    DD    311        ; data cache misses
90    DD    162        ; xmm instr
91
92times (MAXCOUNTERS - ($-CounterTypesDesired)/4)  DD 0
93
94; Number of repetitions of test.
95%define REPETITIONS  8
96
97; Number of threads
98%define NUM_THREADS  3
99
100; Subtract overhead from clock counts (0 if not)
101%define SUBTRACT_OVERHEAD  1
102
103; Number of repetitions in loop to find overhead
104%define OVERHEAD_REPETITIONS  4
105
106; Define array sizes
107%assign MAXREPEAT  REPETITIONS
108
109;------------------------------------------------------------------------------
110;
111;                  global data
112;
113;------------------------------------------------------------------------------
114
115
116; Per-thread data:
117align   CACHELINESIZE, DB 0
118; Data for first thread
119ThreadData:                                                ; beginning of thread data block
120CountTemp:     times  (MAXCOUNTERS + 1)          DD   0    ; temporary storage of counts
121CountOverhead: times  (MAXCOUNTERS + 1)          DD  -1    ; temporary storage of count overhead
122ClockResults:  times   REPETITIONS               DD   0    ; clock counts
123PMCResults:    times  (REPETITIONS*MAXCOUNTERS)  DD   0    ; PMC counts
124align 8, DB 0
125RSPSave                                          DQ   0    ; save stack pointer
126ALIGN   CACHELINESIZE, DB 0                                ; Make sure threads don't use same cache lines
127THREADDSIZE  equ     ($ - ThreadData)                      ; size of data block for each thread
128
129; Define data blocks of same size for remaining threads
130%if  NUM_THREADS > 1
131  times ((NUM_THREADS-1)*THREADDSIZE)            DB 0
132%endif
133
134; Global data
135PThreadData     DQ    ThreadData                 ; Pointer to measured data for all threads
136NumCounters     DD    0                          ; Will be number of valid counters
137MaxNumCounters  DD    NUM_COUNTERS               ; Tell PMCTestA.CPP length of CounterTypesDesired
138UsePMC          DD    USE_PERFORMANCE_COUNTERS   ; Tell PMCTestA.CPP if RDPMC used. Driver needed
139NumThreads      DD    NUM_THREADS                ; Number of threads
140ThreadDataSize  DD    THREADDSIZE                ; Size of each thread data block
141ClockResultsOS  DD    ClockResults-ThreadData    ; Offset to ClockResults
142PMCResultsOS    DD    PMCResults-ThreadData      ; Offset to PMCResults
143Counters:             times MAXCOUNTERS   DD 0   ; Counter register numbers used will be inserted here
144EventRegistersUsed    times MAXCOUNTERS   DD 0   ; Set by MTMonA.cpp
145RatioOut        DD    0, 0, 0, 0                 ; optional ratio output. Se PMCTest.h
146TempOut         DD    0                          ; optional arbitrary output. Se PMCTest.h
147RatioOutTitle   DQ    0                          ; optional column heading
148TempOutTitle    DQ    0                          ; optional column heading
149
150
151
152;##############################################################################
153;#
154;#                 User data
155;#
156;##############################################################################
157ALIGN   CACHELINESIZE, DB 0
158
159; Put any data definitions your test code needs here
160
161UserData           times 10000H  DB 0
162
163
164;------------------------------------------------------------------------------
165;
166;                  Macro definitions
167;
168;------------------------------------------------------------------------------
169
170%macro SERIALIZE 0             ; serialize CPU
171       xor     eax, eax
172       cpuid
173%endmacro
174
175%macro CLEARXMMREG 1           ; clear one xmm register
176   pxor xmm%1, xmm%1
177%endmacro
178
179%macro CLEARALLXMMREG 0        ; set all xmm or ymm registers to 0
180   %if  USEAVX
181      VZEROALL                 ; set all ymm registers to 0
182   %else
183      %assign i 0
184      %rep 16
185         CLEARXMMREG i         ; set all 16 xmm registers to 0
186         %assign i i+1
187      %endrep
188   %endif
189%endmacro
190
191
192;------------------------------------------------------------------------------
193;
194;                  Test Loop
195;
196;------------------------------------------------------------------------------
197SECTION .text   align = 16
198
199;extern "C" int TestLoop (int thread) {
200; This function runs the code to test REPETITIONS times
201; and reads the counters before and after each run:
202
203TestLoop:
204        push    rbx
205        push    rbp
206        push    r12
207        push    r13
208        push    r14
209        push    r15
210%if     WINDOWS                    ; These registers must be saved in Windows, not in Linux
211        push    rsi
212        push    rdi
213        sub     rsp, 0A8H           ; Space for saving xmm6 - 15 and align
214        movaps  [rsp], xmm6
215        movaps  [rsp+10H], xmm7
216        movaps  [rsp+20H], xmm8
217        movaps  [rsp+30H], xmm9
218        movaps  [rsp+40H], xmm10
219        movaps  [rsp+50H], xmm11
220        movaps  [rsp+60H], xmm12
221        movaps  [rsp+70H], xmm13
222        movaps  [rsp+80H], xmm14
223        movaps  [rsp+90H], xmm15       
224        mov     r15d, ecx          ; Thread number
225%else   ; Linux
226        mov     r15d, edi          ; Thread number
227%endif
228       
229; Register use:
230;   r13: pointer to thread data block
231;   r14: loop counter
232;   r15: thread number
233;   rax, rbx, rcx, rdx: scratch
234;   all other registers: available to user program
235
236;##############################################################################
237;#
238;#                 Warm up
239;#
240;##############################################################################
241; Get into max frequency state
242
243%if WARMUPCOUNT
244
245        mov ecx, WARMUPCOUNT / 10
246        mov eax, 1
247        align 16
248Warmuploop:
249        %rep 10
250        imul eax, ecx
251        %endrep
252        dec ecx
253        jnz Warmuploop
254
255%endif
256
257
258;##############################################################################
259;#
260;#                 User Initializations
261;#
262;##############################################################################
263; You may add any initializations your test code needs here.
264; Registers esi, edi, ebp and r8 - r12 will be unchanged from here to the
265; Test code start.
266;
267
268        finit                ; clear all FP registers
269       
270        CLEARALLXMMREG       ; clear all xmm or ymm registers
271
272        imul eax, r15d, 2020h ; separate data for each thread
273        lea rsi, [UserData]
274        add rsi, rax
275        lea rdi, [rsi+120h]
276        xor ebp, ebp
277       
278
279;##############################################################################
280;#
281;#                 End of user Initializations
282;#
283;##############################################################################
284
285        lea     r13, [ThreadData]             ; address of first thread data block
286        imul    eax, r15d, THREADDSIZE        ; offset to thread data block
287        add     r13, rax                      ; address of current thread data block
288        mov     [r13+(RSPSave-ThreadData)],rsp ; save stack pointer
289
290%if  SUBTRACT_OVERHEAD
291; First test loop. Measure empty code
292        xor     r14d, r14d                    ; Loop counter
293
294TEST_LOOP_1:
295
296        SERIALIZE
297     
298        ; Read counters
299%assign i  0
300%rep    NUM_COUNTERS
301        mov     ecx, [Counters + i*4]
302        rdpmc
303        mov     [r13 + i*4 + 4 + (CountTemp-ThreadData)], eax
304%assign i  i+1
305%endrep
306     
307
308        SERIALIZE
309
310        ; read time stamp counter
311        rdtsc
312        mov     [r13 + (CountTemp-ThreadData)], eax
313
314        SERIALIZE
315
316        ; Empty. Test code goes here in next loop
317
318        SERIALIZE
319
320        ; read time stamp counter
321        rdtsc
322        sub     [r13 + (CountTemp-ThreadData)], eax        ; CountTemp[0]
323
324        SERIALIZE
325
326        ; Read counters
327%assign i  0
328%rep    NUM_COUNTERS
329        mov     ecx, [Counters + i*4]
330        rdpmc
331        sub     [r13 + i*4 + 4 + (CountTemp-ThreadData)], eax
332%assign i  i+1
333%endrep
334
335        SERIALIZE
336
337        ; find minimum counts
338%assign i  0
339%rep    NUM_COUNTERS + 1
340        mov     eax, [r13+i*4+(CountTemp-ThreadData)]       ; -count
341        neg     eax
342        mov     ebx, [r13+i*4+(CountOverhead-ThreadData)]   ; previous count
343        cmp     eax, ebx
344        cmovb   ebx, eax
345        mov     [r13+i*4+(CountOverhead-ThreadData)], ebx   ; minimum count       
346%assign i  i+1
347%endrep
348       
349        ; end second test loop
350        inc     r14d
351        cmp     r14d, OVERHEAD_REPETITIONS
352        jb      TEST_LOOP_1
353
354%endif  ; SUBTRACT_OVERHEAD
355
356       
357; Second test loop. Measure user code
358        xor     r14d, r14d                    ; Loop counter
359
360TEST_LOOP_2:
361
362        SERIALIZE
363     
364        ; Read counters
365%assign i  0
366%rep    NUM_COUNTERS
367        mov     ecx, [Counters + i*4]
368        rdpmc
369        mov     [r13 + i*4 + 4 + (CountTemp-ThreadData)], eax
370%assign i  i+1
371%endrep
372
373        SERIALIZE
374
375        ; read time stamp counter
376        rdtsc
377        mov     [r13 + (CountTemp-ThreadData)], eax
378
379        SERIALIZE
380
381;##############################################################################
382;#
383;#                 Test code start
384;#
385;##############################################################################
386
387; Put the assembly code to test here
388; Don't modify r13, r14, r15!
389
390; œœ
391
392
393mov ebp, 100
394align 16
395LL:
396
397%REP 100        ; example: 100 shift instructions
398
399        shr eax, 5
400
401%ENDREP
402
403
404dec ebp
405jnz LL
406
407
408;##############################################################################
409;#
410;#                 Test code end
411;#
412;##############################################################################
413
414        SERIALIZE
415
416        ; read time stamp counter
417        rdtsc
418        sub     [r13 + (CountTemp-ThreadData)], eax        ; CountTemp[0]
419
420        SERIALIZE
421
422        ; Read counters
423%assign i  0
424%rep    NUM_COUNTERS
425        mov     ecx, [Counters + i*4]
426        rdpmc
427        sub     [r13 + i*4 + 4 + (CountTemp-ThreadData)], eax  ; CountTemp[i+1]
428%assign i  i+1
429%endrep
430
431        SERIALIZE
432
433        ; subtract counts before from counts after
434        mov     eax, [r13 + (CountTemp-ThreadData)]            ; -count
435        neg     eax
436%if     SUBTRACT_OVERHEAD
437        sub     eax, [r13+(CountOverhead-ThreadData)]   ; overhead clock count       
438%endif  ; SUBTRACT_OVERHEAD       
439        mov     [r13+r14*4+(ClockResults-ThreadData)], eax      ; save clock count
440       
441%assign i  0
442%rep    NUM_COUNTERS
443        mov     eax, [r13 + i*4 + 4 + (CountTemp-ThreadData)]
444        neg     eax
445%if     SUBTRACT_OVERHEAD
446        sub     eax, [r13+i*4+4+(CountOverhead-ThreadData)]   ; overhead pmc count       
447%endif  ; SUBTRACT_OVERHEAD       
448        mov     [r13+r14*4+i*4*REPETITIONS+(PMCResults-ThreadData)], eax      ; save count       
449%assign i  i+1
450%endrep
451       
452        ; end second test loop
453        inc     r14d
454        cmp     r14d, REPETITIONS
455        jb      TEST_LOOP_2
456
457        ; clean up
458        mov     rsp, [r13+(RSPSave-ThreadData)]   ; restore stack pointer       
459        finit
460        cld
461%if  USEAVX
462        VZEROALL                       ; clear all ymm registers
463%endif       
464
465        ; return REPETITIONS;
466        mov     eax, REPETITIONS
467       
468%if     WINDOWS                        ; Restore registers saved in Windows
469        movaps  xmm6, [rsp]
470        movaps  xmm7, [rsp+10H]
471        movaps  xmm8, [rsp+20H]
472        movaps  xmm9, [rsp+30H]
473        movaps  xmm10, [rsp+40H]
474        movaps  xmm11, [rsp+50H]
475        movaps  xmm12, [rsp+60H]
476        movaps  xmm13, [rsp+70H]
477        movaps  xmm14, [rsp+80H]
478        movaps  xmm15, [rsp+90H]
479        add     rsp, 0A8H           ; Free space for saving xmm6 - 15
480        pop     rdi
481        pop     rsi
482%endif
483        pop     r15
484        pop     r14
485        pop     r13
486        pop     r12
487        pop     rbp
488        pop     rbx
489        ret
490       
491; End of TestLoop
Note: See TracBrowser for help on using the repository browser.