ложное совместное использование в boost::detail::spinlock_pool?

Я наткнулся на этот SO вопрос и перечитав его, в конце концов, я обратил внимание на boost::detail::spinlock_pool.

Целью boost::detail::spinlock_poolявляется снижение потенциальной спин-блокировка путем выбора из массива спин-блокировокс помощью хеширования по shared_pt rадрес. Это кажется разумным решением, но, похоже, есть проблема с реализацией текущей версии (Boost v1.49).

spinlock_poolуправляет статически выделенным массивом из 41 экземпляра spinlock.Похоже, что sizeof(spinlock)==4для платформ, на которые я смотрел, что означает, скажем, x64 с 64-байтными линиями кеша, будет 16 spinlockна каждый кеш. линия.

весь массив занимает все 2 1/2 строки кэша.

Т.е. существует 40%-ная вероятность того, что одна случайная спин-блокировка ложно поделится с другой.

... что, в первую очередь, почти полностью противоречит назначению пула.

Верен ли мой анализ или я упускаю что-то важное?

ОБНОВЛЕНИЕ: Наконец-то я написал небольшую тестовую программу:

#include 
#include 
#include 
#include 
#include 
#include 

using namespace std;

enum { BufferSize = 1<<24,  SLsPerCacheLine = 1 };

int          ibuffer[BufferSize];

using boost::detail::spinlock;
size_t nslp = 41;
spinlock* pslp = 0;

spinlock& getSpinlock(size_t h)
{
  return pslp[ (h%nslp) * SLsPerCacheLine ];
}


void threadFunc(int offset)
{
  const size_t mask = BufferSize-1;
  for (size_t ii=0, index=(offset&mask); ii1 )
  {
    size_t n = wcstoul(argv[1], NULL, 10);
    if ( n>0 )
    {
      nslp = n;
    }
  }

  cout << "Using pool size: "<< nslp << endl;
  cout << "sizeof(spinlock): "<< sizeof(spinlock) << endl;
  cout << "SLsPerCacheLine: "<< int(SLsPerCacheLine) << endl;
  const size_t num = nslp * SLsPerCacheLine;
  pslp = new spinlock[num ];
  for (size_t ii=0; iijoin(); }

  cout << "Elapsed time: " << timer.elapsed() << endl;

  for (size_t ii=0; ii

Я скомпилировал две версии кода, одну с SLsPerCacheLine==1и одну с SLsPerCacheLine== 8. 32-разрядная версия, оптимизированная с помощью MSVS 2010, работает на 4-ядерном процессоре Xeon W3520 с частотой 2,67 ГГц (HyperThreading отключен).

У меня возникли проблемы с получением последовательных результатов этих тестов — иногда наблюдались ложные временные отклонения до 50%. Однако в среднем версия SLsPerCacheLine==8была примерно на 25-30% быстрее, чем версия SLsPerCacheLine==1с таблицей спин-блокировок размером 41.

Это было бы интересно посмотреть, как это масштабируется с большим количеством ядер, NUMA, HyperThreading и т. д. В настоящее время у меня нет доступа к такому оборудованию.

16
задан Community 23 May 2017 в 12:31
поделиться