我在多个进程之间有一个共享内存,以某种方式解释内存。
例如:
DataBlock {
int counter;
double value1;
double ... }
我想要的是计数器以原子方式更新/递增。并在该地址上发生内存释放。
例如,如果我没有使用共享内存,那么它会类似于
std::atomic<int> counter;
atomic_store(counter, newvalue, std::memory_order_release); // perform release operation on the affected memory location making the write visible to other threads
如何为随机内存位置实现此目的(解释为上面的 DataBlock 计数器)?我可以保证地址按照架构(x86 Linux)的要求对齐。
- 使更新原子化 - 如何? (即
atomicupdate(addr, newvalue)
)
- 多核内存同步 - (即
memorysync(addr)
)-我能看到的唯一方法是使用std:: atomic_thread_fence(std::memory_order_release)
- 但这将“建立所有原子和宽松原子存储的内存同步排序” - 这对我来说太过分了 - 我只想同步计数器位置。
欣赏任何想法。
I have a shared memory between multiple processes that interpets the memory in a certain way.
Ex:
DataBlock {
int counter;
double value1;
double ... }
What I want is for the counter to be updated/incremented atomically. And for a memory release to happen on that address.
If I werent using shared memory, for example, it would be something like
std::atomic<int> counter;
atomic_store(counter, newvalue, std::memory_order_release); // perform release operation on the affected memory location making the write visible to other threads
How do I achieve this for a random memory location (interpreted to be DataBlock counter above)? I can guarantee the address is aligned as required by the architecture (x86 Linux).
- Make the update atomic - how? (i.e.
atomicupdate(addr, newvalue)
)
- Memory syncing for multicore - (i.e.
memorysync(addr)
) - only way I can see is using the std::atomic_thread_fence(std::memory_order_release)
- but this will "establish memory synchronization ordering of ALL atomic and relaxed atomic stores" - thats overkill for me - I just want the counter location to be synchronized.
Appreciate any thoughts.
发布评论
评论(3)
我不能在这里权威地回答,但我可以提供可能有帮助的相关信息。
互斥体可以在共享内存中创建和/或创建为跨进程的。 Pthread 有一个特殊的创建标志,我不记得它是否使用共享内存,或者您共享一个句柄。 Linux“futex”可以直接使用共享内存(注意用户地址可能不同,但底层实际地址应该相同)
硬件原子作用于内存而不是过程变量。也就是说,您的芯片不会关心哪些程序正在修改变量,因此最低级别的原子自然会是跨进程的。这同样适用于栅栏。
C++11 无法指定跨进程原子。但是,如果它们是无锁的(检查标志),则很难看出编译器如何实现它们,从而使跨进程无法工作。但是您会对您的工具链和最终平台抱有很大的信心。
CPU 依赖性保证还跟踪实际内存地址,因此只要您的程序在线程形式下是正确的,它在多进程形式下也应该是正确的(就可见性而言)。
Kerrek 是正确的,抽象机并没有真正提到多进程。然而,其同步细节的编写方式使得它们同样适用于进程间,就像适用于多线程一样。这与 #3 相关:编译器很难把它搞砸。
简而言之,没有符合标准的方法可以做到这一点。然而,根据标准定义多线程的方式,您可以对高质量编译器做出很多假设。
最大的问题是原子是否可以简单地分配在共享内存中(放置新的)并工作。显然,只有当它是真正的硬件原子时,这才有效。然而,我的猜测是,使用高质量的编译器/库,C++ 原子应该可以在共享内存中找到。
享受验证行为的乐趣。 :)
I can't answer with authority here, but I can give related information that might help.
Mutexes can be created in shared memory and/or created to be cross-process. Pthread has a special creation flag, I can't remember if that uses shared memory, or you then share a handle. The linux "futex" can use shared memory directly (note the user address may differ, but the underlying real address should be the same)
Hardware atomics work on memory and not process variables. That is, your chip won't care which programs are modifying the variables, the lowest level atomics will thus naturally be cross-process. The same applies to fences.
C++11 fails to specify cross-process atomics. However, if they are lock-free (check the flag) it is hard to see how a compiler could implement them such that cross-process wouldn't work. But you'd be placing a lot of faith in your tool-chain and final platform.
CPU dependency guarantees also track real memory addresses, so as long as your program would be correct in a threaded form it should also be correct in its multi-process form (with respect to visibility).
Kerrek is correct, the abstract machine doesn't really mention multiple processes. However, its synchronization details are written in a way such that they'd equally apply to inter-process as they do to multi-thread. This relates to #3: it'd be hard for a compiler to screw this up.
Short answer, there is no standards compliant way to do this. However, leaning on the way the standard defines mutli-threads there are a lot of assumptions you can make for a quality compiler.
The biggest question is whether an atomic can simply be allocated in shared memory (placement new) and work. Obviously this would only work if it is a true hardware atomic. My guess however is that with a quality compiler/libary the C++ atomics should work find in shared memory.
Have fun verifying behaviour. :)
由于您使用的是 Linux,因此您可以在
counter
地址上使用gcc
原子内置__sync_fetch_and_add()
...根据关于原子内置函数的 gcc 文档 ,这也将实现一个完整的内存栅栏,而不是释放操作,但由于您实际上想要一个读取-修改-写入操作而不是简单的加载(即,递增计数器不仅仅是加载,而且您必须读取,那么修改,最后写回值),全内存栅栏将是更好的选择,可以为此操作强制执行正确的内存排序。Since you're on Linux, you can use the
gcc
atomic built-in__sync_fetch_and_add()
on the address forcounter
... according to the gcc-documentation on atomic built-ins, this will also implement a full memory fence, not a release operation, but since you actually want a read-modify-write operation rather than simply a load (i.e., incrementing a counter is not just a load, but you have to read, then modify, and finally write-back the value), the full-memory fence is going to be a better choice to enforce the correct memory ordering for this operation.我正在查看标准草案 N4820 [atomics.lockfree],它说:
因此,如果您的目标是无地址,则先决条件是无锁,这可以通过 std::atomic 检查。
但是,我不确定如何创建原子对象。将对象放置在共享内存中是否足够好?虽然我在 github 上看到了这样的代码用法,但我还没有找到任何关于此用法的规范。
(编者注:您将指针投射到共享内存,例如
auto p = static_cast*>(ptr);
与以任何其他类型访问共享内存相同。)i am looking at the standard draft N4820 [atomics.lockfree], and it says:
so if you are targeting address-free, the prerequisite is lock-free and this can be checked by std::atomic.
however, i am not sure how
atomic
object shall be created. is it good enough to place the object in shared memory? i have not find out any specification on this usage while i do see such code usage on github.(editor's note: you cast a pointer to shared memory, e.g.
auto p = static_cast<atomic<int>*>(ptr);
Same as accessing shared memory as any other type.)