gpt4 book ai didi

performance - 原子 memcpy 建议

转载 作者:行者123 更新时间:2023-12-01 23:29:01 30 4
gpt4 key购买 nike


在测试程序的可扩展性时,我遇到了必须将 memcpy 操作设置为原子操作的情况。我必须将 64 字节的数据从一个位置复制到另一个位置。
我遇到了一种解决方案,即使用旋转变量:

struct record{
volatile int startFlag;
char data[64];
volatile int doneFlag;
};

伪代码如下

struct record *node;
if ( node->startFlag ==0 ) { // testing the flag
if( CompareAndSwap(node->startFlag , 0 ,1 ) ) { // all thread tries to set, only one will get success and perform memcpy operation
memcpy(destination,source,NoOfBytes);
node->doneFlag = 1; // spinning variable for other thread, those failed in CompAndSwap
}
else {
while ( node->doneFlag==0 ) { // other thread spinning
; // spin around and/or use back-off policy
}
}}

这可以作为原子 memcpy 执行吗?尽管如果执行 memcpy 的线程被抢占(在 memcpy 之前或之后但在设置 didFlag 之前),则其他线程将继续旋转。或者可以做什么来使这个原子化。
情况就像其他线程必须等待,除非数据被复制,因为它们必须与插入的数据和自己的数据进行比较。
我在 startFlag 的情况下使用测试和测试和设置方法来减少一些昂贵的原子操作。自旋锁也是可扩展的,但我已经测量到原子调用比自旋锁具有更好的性能,而且我正在寻找此代码片段中可能出现的问题。由于我使用自己的内存管理器,因此内存分配和免费调用对我来说成本高昂,因此使用另一个缓冲区并复制其中的内容,然后设置指针(因为指针大小处于原子操作下)成本高昂,因为它会需要许多 mem-alloc 和 mem-free 调用。

编辑我没有使用互斥锁,因为它们似乎不可可扩展而且这只是程序的一部分,所以关键部分不是这么小(我知道对于较大的关键部分很难使用原子操作)。

最佳答案

您的代码片段肯定已损坏。 node->startFlag 上有一场竞赛

不幸的是,没有原子方法来复制 64 字节。我认为您在这里有很多选择。

  1. 以原子方式访问node->startFlag。我已经就这个主题写了几篇文章:herehere .
  2. 使用用户模式自旋锁保护整个事物。 Here's a post on the subject
  3. 使用类似 RCU 的方法。您可以阅读有关 RCU here 的信息。简而言之,这个想法是使用指针引用要复制的缓冲区。然后你就可以:
    1. 分配新缓冲区。
    2. 创建其内容(从您的源中进行 memcpy)。
    3. 自动用新缓冲区替换缓冲区。
    4. 等待所有访问旧缓冲区的线程到期并释放它。

希望有帮助。亚历克斯。

关于performance - 原子 memcpy 建议,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6704252/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com