任何人对C/c ++的无锁内存分配器有什么好的经验?
我已经研究了boost和libcds,但我不确定要使用哪个库.
背景,我一直在研究"无锁,无等待,无阻塞,动态完美哈希,可扩展,并发哈希表"*是的我知道这听起来很自命不凡,但这就是所谓的.
无论如何,我正准备开始多线程测试,并且我需要在添加新节点时找出设置内存分配的最佳方法.(当我需要分配指针数组时)
那么有没有人有无锁内存分配的任何良好经验?
是否有一个库实现用C编写的无锁算法(队列,链表和其他)(不是用C++)?我看过像英特尔这样的库,但是我想使用通用库,至少比英特尔库更通用.
在大多数情况下,我写了一些无锁代码,可以在本地读取时正常工作.
本地旋转读取内存是否必然意味着我必须在旋转读取之前始终插入内存屏障?
(为了验证这一点,我设法生成一个读写器组合,导致读者永远不会看到写入的值,在某些非常特定的条件下 - 专用CPU,连接到CPU的进程,优化器一直向上,没有其他工作在循环中完成 - 所以箭头指向那个方向,但我不完全确定旋转内存屏障的成本.)
如果在缓存的存储缓冲区中没有任何内容被刷新,那么旋转内存屏障的成本是多少?即,所有过程都在做(在C中)
while ( 1 ) {
__sync_synchronize();
v = value;
if ( v != 0 ) {
... something ...
}
}
Run Code Online (Sandbox Code Playgroud)
我是否正确地假设它是免费的并且它不会阻碍任何流量的内存总线?
另一种方法是问:内存屏障是否会执行任何操作:刷新存储缓冲区,对其应用失效,并阻止编译器在其位置重新排序读/写?
反汇编,__ sync_synchronize()似乎转化为:
lock orl
Run Code Online (Sandbox Code Playgroud)
从英特尔手册(同样模糊的新手):
Volume 3A: System Programming Guide, Part 1 -- 8.1.2
Bus Locking
Intel 64 and IA-32 processors provide a LOCK# signal that
is asserted automatically during certain critical memory
operations to lock the system bus or equivalent link.
While this output signal is asserted, requests …Run Code Online (Sandbox Code Playgroud) 我在放入boost::lockfree::queue<<T, fixed_sized<false>, ..>
共享内存时遇到问题.我需要它,因为我必须能够将超过65535条消息插入队列,并且fixed_sized队列限制为65535.
以下代码正常工作(但capacity<...>选项暗示fixed_sized<true>):
typedef boost::interprocess::allocator<
MessageT,
boost::interprocess::managed_shared_memory::segment_manager>
ShmemAllocator;
typedef boost::lockfree::queue<
MessageT,
boost::lockfree::capacity<65535>,
boost::lockfree::allocator<ShmemAllocator> >
Queue;
m_segment = new boost::interprocess::managed_shared_memory(
boost::interprocess::create_only, segmentName, size);
Queue* m_queue = m_segment->construct<Queue>(
queueName)(
m_segment->get_segment_manager());
...
m_queue->bounded_push(message);
Run Code Online (Sandbox Code Playgroud)
以下代码也正常工作(但它不使用共享内存):
boost::lockfree::queue<MessageT> q;
....
q.bounded_push(message);
Run Code Online (Sandbox Code Playgroud)
但是当我尝试将它结合起来时:
typedef boost::interprocess::allocator<
MessageT,
boost::interprocess::managed_shared_memory::segment_manager>
ShmemAllocator;
typedef boost::lockfree::queue<
MessageT,
boost::lockfree::allocator<ShmemAllocator> >
Queue;
m_segment = new boost::interprocess::managed_shared_memory(
boost::interprocess::create_only, segmentName, size);
Queue* m_queue = m_segment->construct<Queue>(
queueName)(
m_segment->get_segment_manager());
...
m_queue->bounded_push(message);
Run Code Online (Sandbox Code Playgroud)
它无法使用以下日志进行编译:
In file included from src/model/Queue.h:16:
In file included from /home/uppi/lib/include/boost/lockfree/queue.hpp:24: …Run Code Online (Sandbox Code Playgroud) 在一些关于算法的文章中,有些使用了这个词lockfree,有些则使用了lockless.lockless和之间有什么区别lockfree?谢谢!
更新
http://www.intel.com/content/dam/www/public/us/en/documents/guides/intel-dpdk-programmers-guide.pdf
第5.2节 - "Linux*中的无锁环缓冲区",这是使用"无锁"一词的一个例子
所以我使用a boost::lockfree::spec_queue通过两个boost_threads在我的应用程序中运行两个对象的仿函数进行通信.
一切都很好,除了spec_queue::pop()方法是非阻塞的事实.即使队列中没有任何内容,它也会返回True或False.但是我的队列似乎总是返回True(问题#1).我想这是因为我预先分配了队列.
typedef boost::lockfree::spsc_queue<q_pl, boost::lockfree::capacity<100000> > spsc_queue;
Run Code Online (Sandbox Code Playgroud)
这意味着要有效地使用队列,我必须忙着等待不断使用100%cpu弹出队列.我宁愿不睡任意的时间.我已经在java中使用了其他队列,直到对象可用为止.这可以用std ::或boost :: data结构来完成吗?
我正在尝试在C++ 11中实现一个无锁多个生产者,多个消费者队列.我这样做是为了学习练习,所以我很清楚我可以使用现有的开源实现,但我真的很想知道为什么我的代码不起作用.数据存储在一个环形缓冲区中,显然它是一个"有界MPMC队列".
我已经将它与Disruptor的内容非常接近地建模了.我注意到的事情是它对单个消费者和单个/多个生产者来说绝对正常,它只是多个消费者似乎打破了它.
这是队列:
template <typename T>
class Queue : public IQueue<T>
{
public:
explicit Queue( int capacity );
~Queue();
bool try_push( T value );
bool try_pop( T& value );
private:
typedef struct
{
bool readable;
T value;
} Item;
std::atomic<int> m_head;
std::atomic<int> m_tail;
int m_capacity;
Item* m_items;
};
template <typename T>
Queue<T>::Queue( int capacity ) :
m_head( 0 ),
m_tail( 0 ),
m_capacity(capacity),
m_items( new Item[capacity] )
{
for( int i = 0; i < capacity; ++i )
{ …Run Code Online (Sandbox Code Playgroud) 所以我们正在使用一个版本的boost,这个版本现在很老了,直到升级我需要在C++中为我的代码进行原子CAS操作.(我们还没有使用C++ 0x)
我创建了以下cas函数:
inline uint32_t CAS(volatile uint32_t *mem, uint32_t with, uint32_t cmp)
{
uint32_t prev = cmp;
// This version by Mans Rullgard of Pathscale
__asm__ __volatile__ ( "lock\n\t"
"cmpxchg %2,%0"
: "+m"(*mem), "+a"(prev)
: "r"(with)
: "cc");
return prev;
}
Run Code Online (Sandbox Code Playgroud)
我使用该函数的代码有点如下:
void myFunc(uint32_t &masterDeserialize )
{
std::ostringstream debugStream;
unsigned int tid = pthread_self();
debugStream << "myFunc, threadId: " << tid << " masterDeserialize= " << masterDeserialize << " masterAddress = " << &masterDeserialize << std::endl;
// memory fence
__asm__ …Run Code Online (Sandbox Code Playgroud) c++ multithreading inline-assembly multiprocessing lock-free
我正在寻找一种无锁的方式来Async在F#中的两个s 之间发出信号.我有两个尾递归async函数,我想要一个产生,直到另一个信号发出,然后继续下一个递归.我可以使用一个事件,但看起来.NET事件在内部使用锁.到目前为止,我发现的唯一解决方案是使用来自ntdll.dll的键控事件,但我更喜欢不需要直接引用特定于平台的DLL的解决方案.有什么方法可以使用System.Threading.Interlocked或其他.NET技术来实现这一目标吗?
这是我想要实现的一个简单示例:
let rec loop1 () =
async {
// do work
// somehow signal loop2
return! loop1 ()
}
let rec loop2 state =
async {
// wait for signal from loop1
// do work
return! loop2 state // This would actually be a new state, not the old state
}
Run Code Online (Sandbox Code Playgroud) 简要描述;简介:
下面的代码是《C++ Concurrency in Action 第二版》中无锁队列的实现。队列采用链表作为底层数据结构,采用分割引用计数技术实现。
compare_exchange_strong让我困惑的是,代码中有多个使用acquire内存顺序,但我不明白为什么使用这个顺序。
例如,在对对象count的成员的所有访问中node(见下文),不存在有顺序的存储操作release,但有很多有顺序compare_exchange_strong的操作acquire。
有关此无锁队列的完整代码、我对代码的解释以及我的问题的详细描述,请阅读完整描述部分。
详细描述:
我正在阅读 Anthony Williams 所著的《C++ Concurrency in Action》第二版。本书介绍了如何使用分割引用计数技术来实现无锁队列。我首先根据我的理解简单解释一下代码是如何工作的,以帮助你快速阅读代码。稍后将给出该队列的完整实现。
该实现使用单链表来实现队列。队列保存了指向链表头节点和尾节点的指针,分别是代码中的head和,并指向一个虚拟节点。tailtail
当将元素推入队列时,我们需要将元素值放入 指向的虚拟节点中tail,然后在该节点后面添加一个虚拟节点,并让tail指向新的虚拟节点。
当从队列中弹出一个元素时,我们应该弹出 指向的元素head,然后设置head为head->next。当head和tail指向同一个节点(即哑节点)时,队列为空。
该代码使用引用计数来管理已删除节点的生命周期。与节点相关的引用计数分为两部分,外部引用计数和内部引用计数。外部计数加上内部计数就是该节点的完整引用计数值。外部计数存储在指向节点的指针中(即counted_node_ptr在代码中),而内部计数存储在节点对象内部(即count在代码中)。
为了防止一个线程所指向的对象在解引用指针之前被另一个线程删除,外部计数器必须首先递增以确保该节点不被删除。这是通过increase_external_count()代码完成的。
当外部引用不再引用某个节点时,其中存储的外部计数必须添加到该节点的内部计数中,这是由 完成的free_external_counter()。内部计数存储在count.internal_count节点对象中。并count.external_counters表示引用该节点的外部引用的数量。由于这些外部引用各自拥有自己的外部计数,因此必须将这些计数全部考虑在内。当且仅当内部计数为0并且外部计数器的数量也为0时,该节点才能被安全删除。
对于pop其中未成功指向正在弹出的节点的引用(通常是因为另一个线程已经弹出了该节点),这些引用将被简单地丢弃,但必须减去它们的引用计数。这是由 完成的release_ref()。该函数将节点的内部计数减一。每次引用计数递减,或者内部计数和外部计数合并时,都会检查是否满足删除节点的条件。
下面是书中无锁队列的完整实现:
template<typename T> …Run Code Online (Sandbox Code Playgroud)