There are three main Makefile commands.
$ make all
$ make allBuffer
$ make allTervel
allBuffer
will compile all the tests for buffers, that is buffer_tervel_wf
, buffer_tervel_mcas_lf
, buffer_lock_cg
, buffer_linux_nb
, and buffer_naive_cg
.
allTervel
will compile all the tests for Tervel data structures, that is queue_tervel_wf
, queue_tervel_lf
, mcas_tervel_wf
, vector_tervel_wf
, stack_tervel_lf
, stack_tervel_wf
, hashmap_tervel_wf
, and hashmap_nodel_tervel_wf
.
all
will compile all of the binaries mentioned above.
There is one additional test not compiled by the above scripts because it requires a separate library. That would be buffer_tbb_fg
and if you wish to run this test, start by installing Intel Thread Building Blocks:
$ sudo apt-get install libtbb-dev
Then compile the binaries for it by running
$ make tbb
Another test using an external library was created for this project, a test for the Tsigas queue. At the time of this project's creation, this data structure was supported in the CDS library. It has since been removed due to an ABA problem, therefore it is now deprecated as a Tervel test. If you wish to run this test anyway, the queue is available in libcds 2.1.0.
You will also have to uncomment the lines in the Makefiles to do with tsigasBuffer
. See the Makefile
and Makefile.ringbuffer
. Afterwards, you should be able to compile using.
$ make cds
There are also four variables you may pass into the makefile:
delay
: how long a thread waits before checking the announcement table, 10000 by default, which is quite high
limit
: how many times an op fails before posing an announcement, 10000 by default, which is quite high
version
: just something to help the user name their directories within executables/
, NA by default
As an example of how to use the flags:
$ make allTervel delay=10 limit=10 version=1
Which will compile all Tervel-related test executables under executables/version_1_10_10/
You may run the binaries located in tests/executables/
under a subdirectory with a syntax similar to version_NA_10000_10000
. Inside, you may run one of the binaries with a command syntax such as
$ ./BIN.x F T OP
Where
BIN
is the name of the binary you wish to run,
F
is the flags
T
is the number of threads, and
OP
is the ratio of occurrences for each of the data structure's operations.
Leaving any of these command line parameters blank will default their values to zero.
There is only one flag that is required, and that is -num_threads
with a trailing integer that must be greater than or equal to the sum of all T
s. Therefore, a full sample command for a test would be:
$ ./stack_tervel_lf.x -num_threads 3 2 1 0 1 0 1
Which will run the lock-free Tervel stack test with three threads, the first group consisting of two threads performing 100% inserts and the other group just one thread performing 100% removes. More flags are listed below.
As another example:
$ ./buffer_tervel_wf.x -num_threads 2 2 2 1
Will run the wait-free Tervel buffer test with two threads, each performing approximately 66% enqueue and 33% dequeue.
A list of all the Tervel data structure and algorithm operations in the order that they must be received as command line parameters for the test binaries. Providing an integer for at least one but not all of these ops for their appropriate test will cause the program to list the ops for you.
Buffer/Queue
HashMap
MCAS
Stack
Vector
A list of universal flags that will work for all binaries. -num_threads
is required in order to produce any useful output.
--help |
type: bool |
default: false |
Show all flags. |
-iter_dist |
type: bool |
default: false |
If true, then it iterates between commands. |
-seq_test |
type: bool |
default: false |
If true, then a sequential test is performed. |
-verbose |
type: bool |
default: false |
If true, then verbose output is used. |
-disable_thread_join |
type: bool |
default: false |
Enables skipping of the thread join command, useful if deadlock may occur. |
-execution_time |
type: uint64 |
default: 5 |
The amount of time to run the tests in seconds. |
-main_sleep |
type: uint64 |
default: 0 |
Causes the main thread to sleep before signaling go. Useful for allowing monitors to be attached. |
-num_threads |
type: uint64 |
default: 0 |
The number of executing threads. |
A list of flags for every data structure.
Buffer | |||
---|---|---|---|
-capacity |
type: int32 |
default: 32768 |
The capacity of the buffer. |
-prefill |
type: int32 |
default: 0 |
The number of elements to place in the buffer on init. |
Hash Map | |||
-capacity |
type: int32 |
default: 5 |
The capacity of the HashMap - should be power of two. |
-expansion_factor |
type: int32 |
default: 0 |
The size by which the HashMap expands on collision. 2^expansion_factor = positions. |
-prefill |
type: int32 |
default: 0 |
The number of elements to place in the HashMap on init. |
MCAS | |||
-array_length |
type: int32 |
default: 32 |
The size of the region to test on. |
-mcas_size |
type: int32 |
default: 32 |
The number of words in an mcas operation. |
-multipleObjects |
type: bool |
default: false |
Decides if multiple disjoint mcas operations can occur. |
-overlapping |
type: bool |
default: false |
Decides if the mcas operations can be overlapping. |
Stack | |||
-prefill |
type: int32 |
default: 0 |
The number of elements to place in the stack on init. |
Vector | |||
-capacity |
type: int32 |
default: 0 |
The capacity of the vector. |
-prefill |
type: int32 |
default: 0 |
The number of elements to place in the vector on init. |
For more comprehensive tests, the python files in tests/scripts/
should be used. Before continuing, ensure Python and likwid are installed. See likwid's GitHub. You should also make sure to run the Makefile
first because the default scripts will check for binaries within executables/version_NA_10000_10000/
You may run the script which will run multiple tests simply by.
$ python execute_test.py
Which will prompt you for a config file. Feel free to enter the provided example.config
or create your own. The script will run multiple tests based on the .config
file and place their output in scripts/logs/
.
The syntax of the config file should be fairly straightforward. At the top of the config file are a bunch of universal options that will carry for all tests the Python script will run. This includes:
description
: A string of text that will be echoed in the output .log files.log_git
: A bool that determines if .log files should be created for the current status of the git branch.log_directory
: A file path for where all of the output should be generated.main_sleep_time
: An int for how many seconds the main thread will sleep before signaling go. Useful for allowing monitors to be attached.exe_repetition
: An int for how many times you wish for the exact same execution configuration to runexe_time
: An array of ints where each entry will coincide with a new test given that many seconds to executesystem_name
: A string to describe the machine the test is running on.papi_flag
: Performance API flagsmisc_flags
: Any flags that don't fit into the other categories should go here.thread_levels
: An array listing the different numbers of threads the tests should be ran with. Powers of two recommended.disable_thread_join
: A bool that enables skipping of the thread join command, useful if deadlock may occur.verbose
: A bool that if true, verbose output is used.exe_prefix
: Flags that must go before the executable. Usually used for likwid.Then there are the flags for the tests. The tests
object itself is an array, so you may add more simply with ,[test body goes here]
Within each test, there are more options:
name
: A string of text to describe this specific test.
executables
: An array of the executables that will run. These are the same executables compiled by the Makefile.
path
: The file path to the executables. By default ../executables/version_NA_10000_10000
. That final directory may be different for you based on what options were used when running the Makefile.
flags
: The flags that are specific to this executable's data structure. See previous section.
dist
: An array where each entry is a new configuration for op ratios. It follows the following syntax:
lambda t: None if t < T else "%d OP1 ... OPN %d OP1 ... OPN %d ..." %((t*D1), ...(t*DG))
Where:
T
is the number of threadsG
occurrences of %d
for G
number of thread groupsOP
is each op's ratioD
is a decimal value for the percentage of threads to be doing this particular thread groupFor example, if the following dist entry occurred in a buffer test entry:
lambda t: None if t < 4 else "%d 1 0 %d 0 1" %((t*.25), (t*.75))
Would result in an execution where four or more threads have 25% of threads doing all enqueues and the other 75% doing all dequeues. The reason T
is four is because a thread group configuration with less than four threads cannot be evenly split into a 25:75 thread group configuration. We can be assured that any amount of threads more than four will work if all entries in thread_levels are powers of two.