AMP Lock

From Pheet
Jump to: navigation, search

Contents

Interface

Your own lock implementation should adhere to the following interface:

// Replace Classname with the name of your Lock
template <class Pheet>
class Classname {
public:
  // Typedefs required by Pheet
  typedef HierarchicalBackoffLock<Pheet> Self;
  typedef BasicLockGuard<Pheet, Self> LockGuard; 

  Classname();
  ~Classname();

  void lock();
  void unlock();

  static void print_name() {
    // Should also print some relevant configuration parameters if applicable
    std::cout << "Classname"; 
  }
};

In case your implementation requires parameters to be passed to lock and unlock, you can diverge from the interface as long as you provide a working corresponding implementation of LockGuard.

For locks supporting try_lock (currently not tested by benchmarks, but will be in the future), the following are also required:

bool try_lock();
bool try_lock(long int time_ms);

Add to stress test benchmark

Edit the file test/ds_stress/DsStressTests.cpp. Add an include directive to include your newly created lock.

Add your own implementation to the run_test method by adding this line:

this->stress_test<PheetS2,
    YourLockImplementation,
    LockTest>();

You can also comment out any tests there that you are not interested in. You might also want to try and plug your lock into some lock-based data structures tested here as well.

Running the benchmark

Switch to the stress test benchmark by editing test/settings.h, and setting the macro ACTIVE_TEST to test/test_variants/ds.h. You can change the exact configuration of the test inside ds.h.

The compiler (default: g++), include and library paths can be set in the file settings.mk. To compile, enter the following on the command line:

make test
bin/pheet_test

The output of the benchmarks is in a tab-separated text-format, where each line of data is preceded with a line of headers and can be piped into a file. The output can be converted to a better to process format (csv with one row of headers at the beginning of the file) using the perl-script csvheet in the Pheet main directory.

Header dependencies are not tracked by the Pheet makefile right now, so if you change your lock implementation you might need to run make clean before your changes are applied on a recompile.

Configuration of benchmark and interpretation of results

You can change the configuration of the benchmark by editing test/test_variants/ds.h.

The following line allows to change the number of CPUs used for the experiments. It is recommended to run the tests with different numbers of processors to see scalability trends.

const procs_t ds_stress_test_cpus[] = {1, 2, 4, 8};

So far, Pheet only contains throughput tests. These tests count the number of successful lock/unlock operations by all threads within one second. To give some intuition on fairness we also store the minimum and maximum number of operations by a single thread. Other types of tests (most importantly a test for correctness) will be added in the future.

const int ds_stress_test_types[] = {0};

We allow to explicitly set the random seeds used for the experiments, which adds some determinism to the experiments and thus reproducibility and better comparability between lock implementations. We also use the random seeds to configure the number of repetitions of the experiments (each random seed is one repetition). For your final measurement, to get statistically significant results, you should run each experiment more than once. (As a rule of thumb, 20 experiments should suffice, unless your results exhibit high variance).

const unsigned int ds_stress_test_seed_first = 0;
const unsigned int ds_stress_test_seed_last = 0;

For the experiments all threads share an array of locks, some of which they attempt to acquire at each iteration. The size of the array determines the expected congestion, which can be configured by the following line. Small array sizes allow to determine the fairness of a lock and its performance in situations with high congestion, whereas larger arrays allow to measure performance in situations with low congestion.

const size_t ds_stress_test_num_locks[] = {2, 4, 8, 16};

Currently, we support three different access patterns for the array of locks: 0: Each thread picks a lock from the array uniformly at random, acquires the lock, and unlocks it immediately afterwards 1: Each thread picks a lock uniformly at random, acquires it, and then recursively selects another lock. To avoid deadlocks, this next lock is only acquired if it is left of the previously selected lock in the array, otherwise it ends the recursion, and unlocks all previously acquired locks. 2: Each thread will recursively select a lock and acquire it. To avoid deadlocks, only locks left of the previously selected lock can be chosen. The resursion will randomly terminate, with the probability of termination increasing the further left in the array a lock is. This access pattern will create high congestion on locks with small indices.

const int ds_stress_test_lock_pattern[] = {0, 1, 2};
Personal tools
Namespaces

Variants
Actions
Navigation
Tools