Timing experiments

In this note we describe the experiments we performed so as to time synchronisation constructs.

The complete sources and logs are available, for x86 X86-SPEED (archive) and Power PPC-SPEED (archive).

Contents

1  Generating tests

We build series of 8 tests named X01 to X08 involving from 1 to 8 threads. The code of each thread consists in a write to location, as xi and a read from location say xi+1 (the read of the last thread being from x1). In practice we generate the tests with diyone. For instance X03 for x86 is produced by:

% diyone -arch X86 -name X03 PodWR Fre PodWR Fre PodWR Fre

While X03 for Power is produced by:

% diyone -arch PPC -name X03 PodWR Fre PodWR Fre PodWR Fre

Note that the first test of a batch (X01 for x86 and X01 for Power) is written by hand, as it cannot be induced by a cycle of candidate relaxations. We then build series of synchronised tests, either with offence or by hand.

For x86 from the batch ’X’, we produce three batches:

Notice that in the case of locks, there are two LOCK/UNLOCK sequences per thread, to different lock variables. The alternative of one LOCK/UNLOCK sequence per thread would result in less concurrent execution and has not been tested.

For Power from the batch ’X’, we produce four batches:

2  Running the tests

In the previous, soundness, experiment, the test harness of litmus accounted for an important part of running times. In this experiment we minimise the impact of harness code by:

  1. running test code only once, with litmus options -a 1 -s 1 -r 1;
  2. and inserting the code of each thread of tests in a loop of size 100 · 106, with litmus option -loop 100M.

We perform these settings with litmus configuration file speed.cfg.

The altered test code can be seen in litmus logs, for instance here is the code actually executed by the first thread of F03:

...
 P0          | P1          | P2          ;
 MOV [z],$1  | MOV [x],$1  | MOV [y],$1  ;
 MFENCE      | MFENCE      | MFENCE      ;
 MOV EAX,[x] | MOV EAX,[y] | MOV EAX,[z] ;
...
 _litmus_P0_0_: cmpl $0,%edx
 _litmus_P0_1_: jmp Lit__L1
 _litmus_P0_2_: Lit__L0:
 _litmus_P0_3_: movl $1,(%r8)
 _litmus_P0_4_: mfence
 _litmus_P0_5_: movl (%r9),%eax
 _litmus_P0_6_: decl %edx
 _litmus_P0_7_: Lit__L1:
 _litmus_P0_8_: jg Lit__L0
...

Where %edx is the loop counter. We run all test batches at least five times on our 8 core machines, chianti for x86 and power7 for Power.

3  Measures

3.1  x86

We get the log files C.00 to C.04, of which we extract the following timings (times are wall-clock times of a test run, in seconds):

 C.00C.01C.02C.03C.04
X010.080.080.080.080.08
X020.390.380.390.390.39
X030.290.290.290.290.29
X040.470.470.470.470.47
X050.420.420.400.400.40
X060.520.520.520.530.52
X070.480.490.480.480.47
X080.600.600.600.600.59
 C.00C.01C.02C.03C.04
F011.291.301.301.301.29
F025.765.755.725.815.72
F0315.2815.0215.1814.5517.48
F0418.2418.1014.4014.5514.60
F0517.5917.5317.8717.4217.44
F0617.0016.5316.5614.9117.04
F0716.8815.5715.5017.0016.90
F0819.1517.6916.0315.8616.56
 C.00C.01C.02C.03C.04
A010.720.720.730.720.72
A025.185.185.085.145.24
A0311.6511.5611.5112.0110.81
A0416.9912.1713.2711.5314.26
A0518.2818.5918.5118.0518.64
A0613.7816.4214.3813.6913.16
A0718.3018.5316.8418.2716.02
A0812.5112.4312.2217.8812.29
 C.00C.01C.02C.03C.04
L011.851.851.861.851.86
L0260.9960.0057.5760.2060.74
L0369.2868.3968.4369.8967.88
L0471.3183.9283.7685.0580.58
L0588.0688.2787.2488.0986.55
L0696.73106.3296.39101.9794.78
L07108.0398.5297.4598.9999.07
L0893.5098.4289.5390.4888.08

So as to approximate the time taken by one synchronisation construct, we first select a value for each test, taking the median of the five measures performed. Then, we subtract the value found for a given ’X’ test from the corresponding ’F’, ’A’ or ’L’ values and divide the result by iteration size (108). The final numbers are decent approximations of synchronisation costs. We plot them below, including and excluding the plot for the mapping ’L’:

  

Such time measures are to be treated with caution, due to the non-determinism of the test itself, to the intervention of the system scheduler etc. However, we argue that we can draw a few conclusions from them:

  1. Locks are much more expensive than fences and atomic exchange.
  2. While fast in isolation (nproc=1), fences and atomic exchange get more expensive by a factor of at least ten when communication by shared memory indeed occurs.
  3. mfence and xchg incur similar time penalties.

3.2  Power

We get the log files P.00 to P.04 and P.10 to P.14, of which we extract the following timings (times are wall-clock times, in seconds):

 P.00P.01P.02P.03P.04
X010.140.130.130.130.13
X020.570.330.570.610.58
X030.170.230.170.170.17
X040.240.340.330.320.19
X050.290.430.420.360.31
X060.880.760.920.780.67
X070.370.450.380.370.40
X080.360.390.370.410.47
 P.00P.01P.02P.03P.04
F012.052.052.052.052.05
F027.998.258.958.958.95
F0316.7915.6116.2116.2216.63
F0427.3427.1826.9126.9126.70
F0538.6740.1239.9239.9240.00
F0654.5555.4955.2554.6555.75
F0771.5167.9268.2067.5268.64
F0866.3564.2564.4864.0964.33
 P.00P.01P.02P.03P.04
A014.745.255.245.685.25
A0215.0815.0813.2113.2013.22
A0325.0825.6725.0625.2525.67
A0441.3140.6040.6141.4940.92
A0558.2755.4856.4957.5060.78
A0684.5784.2484.3584.1784.20
A0799.2999.1199.9597.4098.05
A08100.7198.1099.0495.3299.82
 P.00P.01P.02P.03P.04
L019.269.809.809.809.26
L0236.6638.3538.5035.3337.05
L0389.8090.5883.5689.6286.43
L0482.8383.1482.4382.4982.47
L05114.12106.56107.68118.98106.05
L06184.04181.77181.49187.03183.95
L07207.62207.85205.07206.18210.64
L08263.62272.39266.76253.83270.28

Times for batch ’W’ (lwsync) are from different runs:

 P.10P.11P.12P.13P.14
W010.800.820.800.800.89
W022.942.953.213.303.16
W037.767.147.847.377.85
W0414.2014.3313.6214.1414.48
W0520.8721.7322.0222.3722.21
W0631.2630.5630.4030.3429.62
W0728.3529.0031.1331.0228.14
W0822.5030.3729.2628.1531.38

We compute approximations of synchronisation cost as we did for x86:

  

Again, our numbers are to be treated with caution. However, we can draw a few conclusions from them:

  1. Locks are more expensive than fences and atomic pairs.
  2. While fast in isolation (nproc=1), fences and atomic pairs get more expensive by a factor of at least ten when communication by shared memory indeed occurs.
  3. lwsync, sync and sta/fno incur increasing time penalties, both from lwsync to sta/fno and as the number of processors involved grows.

Complete sources and logs: for x86 X86-SPEED (archive) and Power PPC-SPEED (archive).


1
A lwsync fence between a store and a load is useless. However this is irrelevant to our purpose of measuring its cost, as we checked with similar examples on store-store pairs.

This document was translated from LATEX by HEVEA.