【发布时间】:2010-12-25 17:46:15
【问题描述】:
我在 32 位 Windows 上用 C++ 编写了一个低锁定列表。与使用关键部分相比,我得到了很大的改进,但我希望有人能理智地检查我所做的事情是否正确,并且我所做的事情没有任何错误:
#ifndef __LOW_LOCK_STACK_H_
#define __LOW_LOCK_STACK_H_
template< class T > class LowLockStack
{
protected:
struct Entry
{
Entry* pNext;
T* pData;
};
union Header
{
__int64 m_XChg;
struct
{
Entry* m_pNext;
__int16 m_Depth;
__int16 m_Counter;
};
};
Header m_Header;
public:
LowLockStack()
{
m_Header.m_pNext = NULL;
m_Header.m_Depth = 0;
m_Header.m_Counter = 0;
}
~LowLockStack()
{
}
void PushEntry( T* pData )
{
Entry* pEntry = new Entry;
pEntry->pData = pData;
Header header;
Header xchg;
do
{
xchg.m_XChg = m_Header.m_XChg;
header.m_pNext = pEntry;
header.m_Depth = xchg.m_Depth + 1;
header.m_Counter = xchg.m_Counter + 1;
pEntry->pNext = xchg.m_pNext;
} while( _InterlockedCompareExchange64( &m_Header.m_XChg, header.m_XChg, xchg.m_XChg ) != xchg.m_XChg );
}
T* PopEntry()
{
Entry* pEntry = NULL;
Header header;
Header xchg;
do
{
xchg.m_XChg = m_Header.m_XChg;
pEntry = xchg.m_pNext;
if ( pEntry == NULL )
{
return NULL;
}
header.m_pNext = pEntry->pNext;
header.m_Depth = xchg.m_Depth - 1;
} while( _InterlockedCompareExchange64( &m_Header.m_XChg, header.m_XChg, xchg.m_XChg ) != xchg.m_XChg );
T* pRet = pEntry->pData;
delete pEntry;
return pRet;
}
__int32 GetDepth()
{
return m_Header.m_Depth;
}
};
#endif
如果没有错误(我怀疑;))然后将其视为参考实现:D
编辑:考虑到一些批评,我已经更新了代码。
【问题讨论】:
-
你能量化你在关键部分看到的性能增益吗?访问列表的竞争程度如何?有可能获得比无锁更好的性能(例如,每线程队列)。
-
量化性能增益?我没有做足够的测试来量化它。我可以说的是,当我在问题上投入更多线程时,使用 CriticalSections 性能会降低。事实上,单线程提供了迄今为止最好的性能。使用新系统时,代码的线程部分从大约 0.6 秒减少到大约 0.2 秒,当拆分为 4 个线程时。不完美,但对旧系统的改进是地狱般的,我相信你会同意的。
-
当然,由于每个任务的执行速度,争用问题很明显。我不知道对 12 个功能的 16384 个 MFCC 进行日志测试可能会如此之快。旧代码大部分时间都在争夺锁。显然,运行速度较慢的任务会减少争用...
标签: c++ winapi stack interlocked