我在Linux 2.6.我有一个环境,其中2个进程通过简单的消息传递模式实现模拟(使用共享内存)数据交换.
我有一个客户端进程(从父服务器分叉,它是服务器),它将结构(消息)写入创建的内存映射区域(在fork之后):
message *m = mmap(NULL, sizeof(message), PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0)
然后,该指针被写入到队列(在链接列表的形式)转换成是共同的服务器和客户端处理(因为如果事先创建上面相同的代码叉)另一个共享存储器区域.然后由服务器读取该区域,该服务器获得指向消息的指针并对其进行处理.
问题是*m是在fork()之后创建的,当服务器进程尝试访问指向的内存位置时,我得到了分段错误.在客户端创建后,是否可以将该内存区域附加到服务器POST分叉?
注意:我不想在分叉之前将指针映射到消息(然后在服务器之前共享它)因为我通常不知道客户端想要发送到服务器的消息数量,而且可能还有更多消息比一个客户端进程,所以我想只在客户端需要发送消息时创建一个新的共享内存块,并在服务器收到该消息后取消映射.
注意:这是出于学术目的:我知道这不是解决这个问题的最佳方法,但我只需要遵循这条道路.
提前致谢!
我对使用内存映射IO的前景感兴趣,最好利用boost :: interprocess中的工具来实现跨平台支持,将文件中不连续的系统页大小块映射到内存中的连续地址空间.
简化的具体方案:
我有许多"普通旧数据"结构,每个都有一个固定的长度(小于系统页面大小.)这些结构被连接成一个(非常长的)流,其结构的类型和位置由在流中进行它们的那些结构的值.我的目标是在要求苛刻的并发环境中最小化延迟并最大化吞吐量.
我可以非常有效地读取这些数据,通过内存映射它至少是系统页面大小的两倍...并建立一个新的映射,立即读取超出倒数第二个系统页面边界的结构.这使得与普通老式的数据结构交互的代码是一无所知,这些结构是存储器映射...,例如,可以比较使用memcmp()直接在两个不同的结构,而不必关心页边界.
事情变得有趣的是关于更新这些数据流......当它们被(同时)读取时.我想要使用的策略受到系统页面大小粒度的"写入时复制"的启发......基本上是写"覆盖页面" - 允许一个进程读取旧数据而另一个进程读取更新数据.
管理哪些叠加页面以及何时使用不一定是微不足道的......这不是我主要关注的问题.我主要担心的是我可能有一个跨越第4页和第5页的结构,然后更新完全包含在第5页的结构...在第6位写入新页面...当第5页时,将第5页保留为"垃圾收集"决定不再可达.这意味着,如果我将第4页映射到位置M,我需要将第6页映射到内存位置M + page_size ...,以便能够使用现有的(非内存映射)可靠地处理跨页边界的结构意识到)功能.
我正在努力建立最好的策略,而且我受到文件的阻碍,我认为这是不完整的.本质上,我需要将地址空间的分配与内存映射分离到该地址空间.使用mmap(),我知道我可以使用MAP_FIXED - 如果我希望显式控制映射位置......但我不清楚我应该如何保留地址空间以便安全地执行此操作.我可以在没有MAP_FIXED的情况下映射/ dev/zero两个页面,然后使用MAP_FIXED两次将两个页面映射到显式VM地址的分配空间吗?如果是这样,我应该三次打电话给munmap()吗?它会泄漏资源和/或有任何其他不利的开销吗?为了使问题更加复杂,我想在Windows上采用类似的行为......有什么办法可以做到这一点吗?如果我要牺牲我的跨平台野心,是否有完整的解决方案?
-
感谢您的回答,Mahmoud ......我已经读过了,并且认为我已经理解了代码......我已经在Linux下编译了它,它的行为与您的建议一致.
我主要关心的是第62行 - 使用MAP_FIXED.它对mmap做了一些假设,当我阅读我能找到的文档时,我无法确认.您将"更新"页面映射到与最初返回的mmap()相同的地址空间 - 我认为这是'正确' - 即不是恰好在Linux上运行的东西?我还需要假设它适用于文件映射和匿名映射的跨平台.
这个样本肯定让我前进......记录我最终需要的东西可能是在Linux上用mmap()实现的 - 至少.我真正喜欢的是指向文档的指针,该文档显示MAP_FIXED行将在示例演示中运行...并且,理想情况下,从Linux/Unix特定mmap()到独立平台的转换(Boost :: interprocess) )方法.
做的有什么好处:shm_open跟着一个mmap?
为什么不创建一个常规文件,然后将其传递fd给mmap?
我看不到它的优点shm_open- 这些只是参考,不是吗?
我读过全家人.在我看来,"秘密"在于mmaping动作 - 文件"类型"似乎毫无意义.
任何指针都会很好,尤其是性能帐户.
我的上下文是一个(循环可写的)缓冲区(比如128MB),它将被不断地写成一个进程,并且不断地从另一个进程转发.
举个例子:这个 open/mmap方法有什么问题.
编辑
准确地说,下面的一个比另一个更好:
fd = open("/dev/shm/myshm.file", O_CREAT|O_RDWR, S_IRUSR | S_IWUSR);
mem = mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
Run Code Online (Sandbox Code Playgroud)
与
fd = shm_open("/myshm.file", O_RDWR|O_CREATE, S_IRUSR | S_IWUSR);
mem = mmap(...same as before...);
Run Code Online (Sandbox Code Playgroud)
当我在fs open下创建一个带有常规文件的文件/dev/shm,并向其转储了一堆垃圾时,我的可用内存下降了1G,我的可用磁盘空间保持不变.
这两种方法有什么区别?
我试图在ubuntu 11.04上编译以下代码:
#include <boost/interprocess/shared_memory_object.hpp>
#include <iostream>
int main()
{
boost::interprocess::shared_memory_object shdmem(boost::interprocess::open_or_create, "Highscore", boost::interprocess::read_write);
shdmem.truncate(1024);
std::cout << shdmem.get_name() << std::endl;
boost::interprocess::offset_t size;
if (shdmem.get_size(size))
std::cout << size << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
只是为了得到以下错误:
/tmp/cc786obC.o: In function `boost::interprocess::shared_memory_object::priv_open_or_create(boost::interprocess::detail::create_enum_t, char const*, boost::interprocess::mode_t, boost::interprocess::permissions const&)':
shared_memory.cpp:(.text._ZN5boost12interprocess20shared_memory_object19priv_open_or_createENS0_6detail13create_enum_tEPKcNS0_6mode_tERKNS0_11permissionsE[boost::interprocess::shared_memory_object::priv_open_or_create(boost::interprocess::detail::create_enum_t, char const*, boost::interprocess::mode_t, boost::interprocess::permissions const&)]+0xe0): undefined reference to `shm_open'
shared_memory.cpp:(.text._ZN5boost12interprocess20shared_memory_object19priv_open_or_createENS0_6detail13create_enum_tEPKcNS0_6mode_tERKNS0_11permissionsE[boost::interprocess::shared_memory_object::priv_open_or_create(boost::interprocess::detail::create_enum_t, char const*, boost::interprocess::mode_t, boost::interprocess::permissions const&)]+0x116): undefined reference to `shm_open'
shared_memory.cpp:(.text._ZN5boost12interprocess20shared_memory_object19priv_open_or_createENS0_6detail13create_enum_tEPKcNS0_6mode_tERKNS0_11permissionsE[boost::interprocess::shared_memory_object::priv_open_or_create(boost::interprocess::detail::create_enum_t, char const*, boost::interprocess::mode_t, boost::interprocess::permissions const&)]+0x16c): undefined reference to `shm_open'
shared_memory.cpp:(.text._ZN5boost12interprocess20shared_memory_object19priv_open_or_createENS0_6detail13create_enum_tEPKcNS0_6mode_tERKNS0_11permissionsE[boost::interprocess::shared_memory_object::priv_open_or_create(boost::interprocess::detail::create_enum_t, char const*, boost::interprocess::mode_t, boost::interprocess::permissions const&)]+0x1c0): undefined reference to `shm_open'
collect2: …Run Code Online (Sandbox Code Playgroud) 在Compute Capability 2.0(Fermi)发布之后,我想知道是否有任何用例共享内存.也就是说,何时使用共享内存比让L1在后台执行魔术更好?
共享内存是否只是为了让CC <2.0设计的算法在没有修改的情况下高效运行?
要通过共享内存进行协作,块中的线程会写入共享内存并与之同步__syncthreads().为什么不简单地写入全局内存(通过L1),并与__threadfence_block()?同步?后一个选项应该更容易实现,因为它不必涉及值的两个不同位置,并且它应该更快,因为没有从全局到共享内存的显式复制.由于数据在L1中缓存,因此线程不必等待数据实际上一直到全局内存.
使用共享内存,可以保证在整个块的持续时间内放置的值保持不变.这与L1中的值相反,如果它们不经常使用,则会被逐出.是否有任何情况下,在共享内存中缓存这些很少使用的数据比让L1根据算法实际具有的使用模式管理它们更好?
我的目标是将数据从C++进程传递到Java进程,然后再返回结果.
我通过命名管道实现了这一点,但我更愿意共享数据而不是传递或复制它,假设访问速度更快.
最初,我想过在C++中创建一个可以用Java编写和读取的共享段,但我不确定这是否可以通过JNI实现,更不用说安全了.
我相信在Java中可以使用ByteBuffer.allocateDirect分配内存,然后使用GetDirectBufferAddress来访问C++中的地址,但是如果我是正确的,这是针对JNI中的本机调用,我无法在C++进程中获取此地址?
丢失.
提前谢谢了.
以下代码并行化for循环.
import networkx as nx;
import numpy as np;
from joblib import Parallel, delayed;
import multiprocessing;
def core_func(repeat_index, G, numpy_arrary_2D):
for u in G.nodes():
numpy_arrary_2D[repeat_index][u] = 2;
return;
if __name__ == "__main__":
G = nx.erdos_renyi_graph(100000,0.99);
nRepeat = 5000;
numpy_array = np.zeros([nRepeat,G.number_of_nodes()]);
Parallel(n_jobs=4)(delayed(core_func)(repeat_index, G, numpy_array) for repeat_index in range(nRepeat));
print(np.mean(numpy_array));
Run Code Online (Sandbox Code Playgroud)
可以看出,要打印的期望值是2.但是,当我在集群(多核,共享内存)上运行我的代码时,它返回0.0.
我认为问题是每个工作者都创建自己的numpy_array对象副本,并且不更新在main函数中创建的副本.如何修改代码numpy_array以便更新numpy数组?
所以我在一台带有GeForce GTX 980显卡的Windows 10机器上安装了TensorFlow的GPU版本.
不可否认,我对显卡知之甚少,但据dxdiag说它确实有:
4060MB 专用存储器(VRAM)和;
8163MB 共享内存
总计约12224MB.
然而,我注意到,这种"共享"记忆似乎毫无用处.当我开始训练模型时,VRAM将填满,如果内存需求超过这些4GB,TensorFlow将因"资源耗尽"错误消息而崩溃.
当然,我可以通过选择适当低的批量大小来防止达到这一点,但我想知道是否有办法利用这些"额外" 8GB的RAM,或者如果是这样,TensorFlow需要内存专用.
我有一个C++ .NET应用程序和一个C#.NET应用程序.我希望他们通过共享内存进行通信.
.NET版本2.0怎么可能?
主要是想共享一个队列对象.
我有两个不同的Windows应用程序(两个不同的人编写代码).一个用C++编写,另一个用C#编写.我需要一些方法来在它们之间共享RAM中的数据.必须写入数据,而另一个只读取写入的数据.我应该用什么来使它最有效和最快速?谢谢.