C++ 有人尝试过C+的事务内存吗+;?
我正在查看Intel的“whatif”站点及其事务性内存编译器(每个线程都必须进行原子提交或回滚系统内存,就像数据库一样)C++ 有人尝试过C+的事务内存吗+;?,c++,multithreading,locking,intel,transactional-memory,C++,Multithreading,Locking,Intel,Transactional Memory,我正在查看Intel的“whatif”站点及其事务性内存编译器(每个线程都必须进行原子提交或回滚系统内存,就像数据库一样) 这似乎是一个很有前途的方法来取代锁和互斥,但我找不到很多推荐。这里有人有什么意见吗?在某些情况下,我认为这是有用的,甚至是必要的 然而,即使处理器具有使该过程更容易的特殊指令,与互斥或信号量相比,仍然存在较大的开销。根据它的实现方式,它还可能影响实时性能(必须停止中断,或防止它们写入共享区域) 我的期望是,如果实现了这一点,那么它只需要给定内存空间的一部分,因此影响可能是有
这似乎是一个很有前途的方法来取代锁和互斥,但我找不到很多推荐。这里有人有什么意见吗?在某些情况下,我认为这是有用的,甚至是必要的 然而,即使处理器具有使该过程更容易的特殊指令,与互斥或信号量相比,仍然存在较大的开销。根据它的实现方式,它还可能影响实时性能(必须停止中断,或防止它们写入共享区域) 我的期望是,如果实现了这一点,那么它只需要给定内存空间的一部分,因此影响可能是有限的
-Adam我没有使用英特尔的编译器,但是,Herb Sutter对此有一些有趣的评论 从 您是否对事务性内存的使用感兴趣,或者这一概念对于大多数开发人员来说太难理解? 目前还不可能回答是谁在使用它,因为它还没有上市。英特尔有一个软件事务内存编译器原型。但如果问题是“开发人员使用它太难了吗?”答案是我当然希望不是。关键是它比锁容易多了。这是研究视野中唯一一件让我们有希望大大减少锁的使用的重要事情。它永远不会完全替换锁,但我们唯一的希望是部分替换它们 有一些限制。特别是,某些I/O本质上不是事务性的—您不能接受一个原子块,该原子块提示用户输入其名称并从控制台读取名称,如果与另一个事务冲突,则自动中止并重试该块;如果您提示用户两次,用户可以分辨出差异。不过,事务性内存非常适合只涉及内存的东西
据我所知,每个主要的硬件和软件供应商在研发中都有多种事务性内存工具。有关于基本问题理论答案的会议和学术论文。我们还没有到T型车的阶段,我们可以把它运出去。您可能会看到早期的有限原型,在这些原型中,您无法执行无限事务性内存,您只能读取和写入,例如,100个内存位置。不过,这对于启用更多无锁算法仍然非常有用 Dobb博士去年发表了一篇关于这个概念的文章:Calum Grant的事务编程--
它包括一些使用他的示例库的示例、比较和结论。Sun Microsystems宣布,他们将于明年发布一款新处理器,代号为Rock,该处理器具有事务性内存的硬件支持。它会有一些限制,但这是一个很好的第一步,可以让程序员更容易地用事务替换锁/互斥锁,并且期望它具有良好的性能 Sun公司研究事务性记忆和摇滚乐的研究人员之一马克·莫尔(Mark Moir)对此主题进行了一次有趣的演讲,请看以下内容 有关Sun关于Rock和事务性内存的更多信息和公告,请参阅 义务教师:)
最后,在威斯康星大学麦迪逊分校,包含了关于事务内存的大部分研究的书目,无论是硬件相关的还是软件相关的。 < P>我已经在一些函数编程思想的基础上构建了组合STM库。它不需要任何编译器支持(除了使用C++17),也不会带来新的语法。通常,它采用来自Haskell的接口 因此,我的库有几个很好的特性:
- 一元组合的。每个事务都是名为
的自定义monad中的一个计算。您可以将一元事务合并为更大的一元事务STML
- 事务与数据模型分离。您可以使用事务变量(
)构建并发数据模型,并在其上运行事务TVars
- 有
组合器。它允许您重新运行事务。对于构建简短易懂的事务非常有用重试
- 有不同的一元组合来表示计算
- 有
。每个计算都应该在某个上下文中运行,而不是在全局运行时中运行。因此,如果需要几个独立的STM集群,那么可以有许多不同的上下文上下文
- 实现在概念上非常简单。至少在Haskell中是这样的,但是我不得不重新发明几种C++实现方法,因为缺少对函数编程的良好支持。
库显示了非常好的稳定性和鲁棒性,即使我们认为它是实验性的。此外,我的方法在性能、功能、全面性等方面为改进库提供了很多可能性
为了演示它的工作,我已经解决了用餐哲学家
任务。您可以在下面的链接中找到代码。样本交易:
STML<bool> takeFork(const TVar<Fork>& tFork)
{
STML<bool> alreadyTaken = withTVar(tFork, isForkTaken);
STML<Unit> takenByUs = modifyTVar(tFork, setForkTaken);
STML<bool> success = sequence(takenByUs, pure(true));
STML<bool> fail = pure(false);
STML<bool> result = ifThenElse(alreadyTaken, fail, success);
return result;
};
STML takeFork(const TVar&t工作)
{
STML alreadyTaken=带TVAR(tWork,IsForkTake);
STML takenByUs=modifyTVar(tFork,setforktake);
STML成功=序列(takenByUs,纯(真));
STML失败=纯(假);
STML结果=ifThenElse(已完成、失败、成功);
返回结果;
};
更新
我写了一篇教程,你可以找到