我遇到了这个问题并阅读它最终让我看到了boost::detail::spinlock_pool.
其目的boost::detail::spinlock_pool是spinlock通过在shared_ptrs地址上进行散列选择s 数组来减少对全局自旋锁的潜在争用.这似乎是一个合理的解决方案,但目前(Boost v1.49)版本的实现似乎存在问题.
spinlock_pool管理静态分配的41个spinlock实例的数组.看来,sizeof(spinlock)==4对于我所看到的平台 - 这意味着,例如x64与64字节spinlock的高速缓存行,每个高速缓存行将有16 秒.
即整个阵列跨越所有2 1/2缓存线.
也就是说,有一个随机螺旋锁错误共享的可能性为40%.
......首先几乎完全打败了游泳池的目的.
我的分析是正确的还是我遗漏了一些重要的东西?
更新: 我终于写了一个小的基准程序:
#include <boost/shared_ptr.hpp>
#include <boost/thread.hpp>
#include <boost/timer.hpp>
#include <iostream>
#include <vector>
#include <stdlib.h>
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 …Run Code Online (Sandbox Code Playgroud) 我有以下任务来演示虚假共享并编写了一个简单的程序:
#include <sys/times.h>
#include <time.h>
#include <stdio.h>
#include <pthread.h>
long long int tmsBegin1,tmsEnd1,tmsBegin2,tmsEnd2,tmsBegin3,tmsEnd3;
int array[100];
void *heavy_loop(void *param) {
int index = *((int*)param);
int i;
for (i = 0; i < 100000000; i++)
array[index]+=3;
}
int main(int argc, char *argv[]) {
int first_elem = 0;
int bad_elem = 1;
int good_elem = 32;
long long time1;
long long time2;
long long time3;
pthread_t thread_1;
pthread_t thread_2;
tmsBegin3 = clock();
heavy_loop((void*)&first_elem);
heavy_loop((void*)&bad_elem);
tmsEnd3 = clock();
tmsBegin1 = clock();
pthread_create(&thread_1, NULL, heavy_loop, …Run Code Online (Sandbox Code Playgroud) 当不同的变量位于同一个缓存行中时,您可能会遇到错误共享,这意味着即使两个不同的线程(在不同的核心上运行)正在访问两个不同的变量,如果这两个变量位于同一个缓存行中,您将拥有性能命中,因为每次都会触发缓存一致性.
现在说这些变量是原子变量(通过原子我的意思是引入内存栅栏的变量,比如atomic<t>C++),会在那里假共享物质,或者原子变量是否在同一个缓存行中并不重要,如据说他们无论如何都会引入缓存一致性.换句话说,将原子变量放在同一个缓存行中会使应用程序变慢而不是将它们放在同一个缓存行中吗?
而不是sizeof(std::atomic<bool>)==1?
一个互斥体可以通过一个简单的实现std::atomic<bool>,所以我认为互斥体的大小可以小到那个,或者可能是4(32位).
c++ ×3
c ×2
c++11 ×2
boost ×1
boost-thread ×1
caching ×1
mutex ×1
pthreads ×1
shared-ptr ×1
x86-64 ×1