需要使用IPC在OS X 10.4及更高版本上将大量数据(200kb +)从子进程传递到父进程,我在Unix上读取共享内存,特别是System V和POSIX共享内存机制.然后我意识到mmap()可以与MAP_ANON和MAP_SHARED标志一起使用来做类似的事情(或者只是使用MAP_SHARED标志,如果我不介意正在创建常规文件).
我的问题是,有没有理由不使用mmap()?它似乎更简单,内存仍然是共享的,如果我使用MAP_ANON,它不必创建真实的文件.我可以在父进程中创建文件,然后fork()和exec()子进程并在子进程中使用它.
问题的第二部分是,这种方法不充分的原因是什么,并且必须使用SysV或POSIX共享内存机制?
请注意,我计划使用其他通信所需的管道进行同步,即父级通过管道请求数据,子级将其写入共享内存,并通过管道响应其准备就绪.没有涉及多个读者或作家.便携性不是优先事项.
我正在LynxOS SE(POSIX conformant)系统上实现两个进程,它们将通过共享内存进行通信.
一个过程将充当"生产者"而另一个过程将充当"消费者".在多线程系统中,我的方法是使用互斥和condvar(条件变量)对,消费者在condvar(with pthread_cond_wait)上等待,生产者pthread_cond_signal在更新共享内存时用信号通知它(with ).
如何在多进程架构而不是多线程架构中实现这一目标?
是否有LynxOS/POSIX方法来创建可在进程之间使用的condvar/mutex对?
或者在这种情况下,其他一些同步机制更合适吗?
我在使用Open-MPI 1.3.3的集群上使用CentOS 5.4 x86_64和Boost 1.42.0.我正在编写一个共享库,它使用共享内存来存储大量数据,供多个进程使用.还有一个加载器应用程序,它将读取文件中的数据并将它们加载到共享内存中.
当我运行加载器应用程序时,它确定了准确存储数据所需的内存量,然后增加了25%的开销.对于几乎每个文件,它将超过2演出数据.当我使用Boost的Interprocess库发出内存请求时,它表示它已成功保留了所请求的内存量.但是当我使用start开始使用它时,我得到一个"总线错误".据我所知,总线错误是访问内存段可用范围之外的内存的结果.
所以我开始研究如何在Linux上共享内存以及检查什么以确保我的系统配置正确以允许大量共享内存.
/proc/sys/kernel/shm*:
shmall - 4294967296(4 Gb)shmmax - 68719476736(68 Gb)shmmni - 4096ipcs -lm命令:
------ Shared Memory Limits -------- max number of segments = 4096 max seg size (kbytes) = 67108864 max total shared memory (kbytes) = 17179869184 min seg size (bytes) = 1
据我所知,这些设置表明我应该能够为我的目的分配足够的共享内存.所以我创建了一个在共享内存中创建大量数据的精简程序:
#include <iostream>
#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/interprocess/allocators/allocator.hpp>
#include <boost/interprocess/containers/vector.hpp>
namespace bip = boost::interprocess;
typedef bip::managed_shared_memory::segment_manager segment_manager_t;
typedef bip::allocator<long, segment_manager_t> long_allocator;
typedef bip::vector<long, long_allocator> long_vector;
int …Run Code Online (Sandbox Code Playgroud) 我想在两个应用程序之间共享数组数据.在我看来,第一个程序创建数组,第二个程序可以从已分配的内存区读取数组.该数组不是动态数组.
我发现了一种使用OpenFileMapping和分享指针的方法MapViewOfFile.我没有运气实现数组共享,我想我还不想使用IPC方法.
有可能计划这样的方案(共享数组)吗?我的目的是最大限度地减少内存使用和读取数据.
我正在尝试将(循环)队列(在C中)设计/实现为共享内存,以便它可以在多个线程/进程之间共享.
队列结构如下:
typedef struct _q {
int q_size;
int q_front;
int q_rear;
int *q_data;
}queue;
Run Code Online (Sandbox Code Playgroud)
它支持以下功能:
int empty_q(queue *q);
int display_q(queue *q);
int create_q(queue **q, int size);
int delete_q(queue **q);
int enqueue(queue *q, int data);
int dequeue(queue *q, int *data);
Run Code Online (Sandbox Code Playgroud)
根据用户提到的队列大小,q_data的内存将在create_q()中分配.
问题:如何使用"sys/shm.h"中提供的系统函数为此队列创建共享内存?用于创建/附接/检索/删除使用共享存储器用于队列数据结构中的任何的代码段/示例shmget的(),的shmat(),了shmctl()等将是一个很大的帮助.
我在数据结构上寻找一些数据并行算法,例如列表或图形,它们不使用同步但是利用关键部分来保持状态一致.
到目前为止,我只遇到了算法
同步:它们处理它们更改的数据的本地副本,并在某些时间段交换它们的当前状态以进行下一步(例如,单步并行本地搜索),或者
无竞争条件:它们细分数据结构,使得每个部分可以使用共享内存单独安全地处理(例如并行Quicksort)
你知道任何可理解的(半)异步算法吗?
编辑:我使用HT Kung 的技术报告同步和异步并行算法的多处理器术语.
编辑2:为了澄清术语,本文区分了不同类型的算法:
algorithm parallel-processing synchronization asynchronous shared-memory
当我分叉我的进程时,如何防止GC激发写时复制?我最近一直在分析垃圾收集器在Ruby中的行为,因为我在程序中遇到了一些内存问题(即使对于相当小的任务,我的60核0.5Tb机器上的内存耗尽).对我来说,这确实限制了ruby在多核服务器上运行程序的实用性.我想在这里介绍我的实验和结果.
垃圾收集器在分叉期间运行时会出现问题.我调查了三个案例来说明这个问题.
情况1:我们使用数组在内存中分配了大量对象(字符串不超过20个字节).使用随机数和字符串格式创建字符串.当进程分叉并强制GC在子进程中运行时,所有共享内存都是私有的,导致初始内存重复.
情况2:我们使用数组在内存中分配了很多对象(字符串),但是使用rand.to_s函数创建了字符串,因此我们删除了与前一种情况相比的数据格式.我们最终使用的内存较少,可能是因为垃圾较少.当进程分叉并强制GC在子进程中运行时,只有部分内存变为私有.我们有重复的初始内存,但程度较小.
情况3:与之前相比,我们分配的对象更少,但对象更大,因此分配的内存量与之前的情况相同.当进程分叉并且我们强制GC在子进程中运行时,所有内存保持共享,即没有内存重复.
在这里,我粘贴用于这些实验的Ruby代码.要在不同情况之间切换,只需更改memory_object函数中的"option"值即可.在Ubuntu 14.04计算机上使用Ruby 2.2.2,2.2.1,2.1.3,2.1.5和1.9.3测试了代码.
案例1的示例输出:
ruby version 2.2.2
proces pid log priv_dirty shared_dirty
Parent 3897 post alloc 38 0
Parent 3897 4 fork 0 37
Child 3937 4 initial 0 37
Child 3937 8 empty GC 35 5
Run Code Online (Sandbox Code Playgroud)
完全相同的代码是用Python编写的,在所有情况下,CoW都可以正常工作.
案例1的示例输出:
python version 2.7.6 (default, Mar 22 2014, 22:59:56)
[GCC 4.8.2]
proces pid log priv_dirty shared_dirty
Parent 4308 post alloc 35 0
Parent 4308 4 fork 0 35
Child 4309 4 initial 0 35
Child 4309 10 …Run Code Online (Sandbox Code Playgroud) 我已经解决了这个问题一个星期了,而且它变得非常令人沮丧,因为每次我实现一个更简单但相似的我需要做的比例示例时,事实证明多处理会捏造它.它处理共享内存的方式令我困惑,因为它非常有限,它可能会很快变得无用.
所以我的问题的基本描述是我需要创建一个进程,该进程在一些参数中传递以打开图像并创建大小为60x40的大约20K补丁.这些补丁一次保存到列表2中,需要返回到主线程,然后由GPU上运行的其他2个并发进程再次处理.
过程和工作流程以及所有大部分都需要处理的事情,我现在需要的是最容易被认为是最困难的部分.我无法保存并将带有20K补丁的列表返回到主线程.
第一个问题是因为我将这些补丁保存为PIL图像.然后我发现添加到Queue对象的所有数据都必须被pickle.第二个问题是我然后将补丁转换为每个60x40的数组并将它们保存到列表中.而现在仍然不起作用?显然,当您调用queue_obj.get()程序挂起时,队列可以保存有限数量的数据.
我尝试过很多其他的东西,而且我尝试的每一件新东西都不起作用,所以我想知道是否有人有一个库的其他建议我可以使用它来共享对象而没有所有模糊的东西?
这是我正在看的一种示例实现.请记住,这完全正常,但完全实现不会.我确实有代码打印信息性消息,以确保保存的数据具有完全相同的形状和一切,但由于某种原因它不起作用.在完整实现中,独立进程成功完成,但在q.get()处冻结.
from PIL import Image
from multiprocessing import Queue, Process
import StringIO
import numpy
img = Image.open("/path/to/image.jpg")
q = Queue()
q2 = Queue()
#
#
# MAX Individual Queue limit for 60x40 images in BW is 31,466.
# Multiple individual Queues can be filled to the max limit of 31,466.
# A single Queue can only take up to 31,466, even if split up in different puts.
def rz(patch, qn1, qn2):
totalPatchCount = 20000
channels …Run Code Online (Sandbox Code Playgroud) python multithreading shared-memory multiprocessing python-multiprocessing
我在POSIX模型中有两个不同应用程序之间的共享动态数组.我希望有能力改变它的大小而不复制.不幸的是我无法找到正确的解决方案来增加和减少C语言中的POSIX共享内存.在网络上,我发现很多文档都有不好的解释和可怜的例子.我设法找到了一些有趣的话题,但所有这些话都不适合我:
"Linux系统编程" - "将文件映射到内存"部分:"调整映射大小" - 没有工作示例来调整SHM的大小.
如何实现动态共享内存大小调整? - 仅供参考.没有例子.
mremap函数无法分配新内存 - 收藏的答案有误.
c/linux - ftruncate和POSIX共享内存段 - rszshm根本不使用mremap().它复制内存.最坏的方式.
我已经开发了一个例子,因为我理解文档.不幸的是它无法正常工作.请给我一个建议,我错了.请非常友好地给我一个有效的例子.
在文档中我发现我必须在mremap()之前使用ftruncate(),但是我找不到使用它们的正确语法.此外,mremap()适用于对齐的内存页面.在这种情况下如何正确增加共享内存?
/* main.c */
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <errno.h>
int main(void)
{
size_t size_of_mem = 1024;
int fd = shm_open("/myregion", O_CREAT | O_RDWR,
S_IRWXO | S_IRUSR | S_IWUSR);
if (fd == -1)
{
perror("Error in shm_open");
return EXIT_FAILURE;
}
if (ftruncate(fd, size_of_mem) …Run Code Online (Sandbox Code Playgroud) 我正在尝试将大量数据缓存在物理内存中,并为本地环境中的其他进程共享它们.所以我想出了MMF并阅读了Microsoft MMF文档并看了几个例子并开始调整这样的代码.
MemoryMappedFile MMF = MemoryMappedFile.CreateNew("Features", MaxSize);
.
.
.
using (MemoryMappedViewStream stream = MMF.CreateViewStream())
{
BinaryWriter write = new BinaryWriter(stream);
.
.
.
// Fetched the data from database and store it into Rowdata variable.
while (Rowdata.Read())
{
byte[] data = Rowdata.GetFieldValue<byte[]>(0);
write.Write(data);
}
}
Run Code Online (Sandbox Code Playgroud)
它不会将数据保存在内存中
我正在研究IVSSharedMemory,但内存大小应该远高于此.
当我创建内存映射文件时,有什么我忘了做的吗?请告诉我是否有.在我注意到这种意外行为之后我用谷歌搜索了这个,有些人说它是虚拟内存.但我不禁想到这不是真的,因为在文件中,它在下面的部分解释了这一点.
非持久内存映射文件
CreateNew和CreateOrOpen方法创建一个未映射到磁盘上现有文件的内存映射文件.
提前致谢.只是确认MMF设计的内容也会受到赞赏.
UPDATE
它确实是一个虚拟内存.正如Mike z评论的那样,我检查了我的应用程序在VMMAP工具中保留的记忆,结果就是我想要看到的内容.
但是看看这个,提交的内存量已经改变了.当我的应用完全加载所有数据时会发生这种情况.我可以猜测,之前的大小只是表明MaxSize我创建MMF时分配的大小.
是去了物理磁盘空间还是什么?
我读了很多关于MemoryMappedFile的内容,试图看看地下有什么.但我仍然不明白为什么会这样.说真的,数据在哪里?我在哪里可以检查它?