shared-memory 相关问题

可由多个程序同时访问的内存

如何使用 OpenMP 在共享内存系统上并行化 Fortran 中的嵌套循环,并将线程显式分配给内部和外部循环?

我正在开发一个带有嵌套循环的 Fortran 程序,我想使用 OpenMP 对其进行并行化。该程序在共享内存多处理器系统上运行,我想要以下内容: 内循环...

回答 1 投票 0

python3多处理SharedMemory无法解决连接现有内存

我想要完成的是首先运行 testb.py 并创建共享内存,然后运行 testc.py 并连接到它。然后关闭 testc.py 并重新运行它并再次连接到共享内存。但我坚持

回答 1 投票 0

如何查看docker容器的共享内存大小?

有没有办法从docker容器内部访问shm-size? shm-size是docker run中的可选参数 例如 docker run -it --shm-size=256m oracle11g /bin/bash 然而,我该如何

回答 2 投票 0

df 报告磁盘使用情况,但共享内存 /dev/shm 中没有文件

我正在尝试使用共享内存/c++ 进行编程。 我有多个进程访问共享内存片段,然后在执行过程中取消链接,并在完成后链接到另一个片段

回答 1 投票 0

屏障之后的写入器如何在屏障之前的写入之前可见?

在linux内核的内存屏障文档(Documentation/memory-barriers.txt)中,有一些示例表明内存屏障之后的写入器在...之前的写入之前是可见的。

回答 3 投票 0

在 Python 中利用不返回任何值的函数进行多重处理

考虑Python中的以下代码: 从多处理导入池 数据 = [4] * 10 定义更新(j): 数据[j] += j ** 2 def 求解器(): 将 Pool(8) 作为 po: po.map(更新,范围(10...

回答 1 投票 0

在Python中使用多处理和“void”之类的函数

考虑以下Python代码: 从多处理导入池 数据 = [4] * 10 定义更新(j): 数据[j] += j ** 2 def 求解器(): 将 Pool(8) 作为 po: po.map(更新,范围(10...

回答 1 投票 0

numpy 数组的共享内存大小

在 superfastpython.com 上看到的示例中,用于支持一维 numpy 数组的共享内存段的大小计算为元素数量乘以数据类型...

回答 1 投票 0

SharedMemory numpy 数组多处理问题

问题 我有很多数据,首先使用 SharedMemory 加载到 RAM 中,然后使用 multiprocessing.Pool.map 读取许多子进程。 代码 这是一个简化版本(不是真的

回答 1 投票 0

具有动态分配共享内存的Cupy

考虑通过此链接中的 CUPY 在 python 中使用的以下 CUDA 内核 add_kernel = cp.RawKernel(r''' 外部“C”__global__ void my_add(const float* x1, const float* x2, float*...

回答 1 投票 0

如何在Python joblib中写入共享变量

以下代码并行化了一个for循环。 将网络x导入为nx; 将 numpy 导入为 np; from joblib import 并行,延迟; 导入多重处理; def core_func(repeat_index, G, numpy_arrary_2D...

回答 3 投票 0

在不同实例之间共享nodejs中的对象

我需要在不同节点进程或集群之间共享一些对象或完整模块,我搜索了很多博客都没有得到满意的答案。 如果这是不可能做到的那么任何想法......

回答 2 投票 0

NodeJs 在进程之间共享对象

我正在为 Nodejs 创建一个缓存模块,它需要使用子进程来利用多个 CPU。 我想将数据存储在主进程的索引中,或者最好在子进程中,例如......

回答 2 投票 0

为什么在硬件保证一致性的情况下会出现竞争条件

#包括 #包括 #包括 #包括 #包括 使用命名空间 std::chrono; const int nthreads = 4; 常量 int64_t ndata =

回答 1 投票 0

在所有 PHP 进程之间共享变量/内存

是否可以在所有 PHP 进程之间共享变量和数组而不重复它们? 使用 memcached,我认为 PHP 会重复使用的内存: $array = $memcache->get('array'); $ar...

回答 5 投票 0

如何解释进程的top命令内存使用情况?

我想了解作为进程的 top 命令一部分显示的 VIRT、RES 和 SHR 值的重要性。 我编写了一个简单的程序,它本身不分配任何私有内存......

回答 1 投票 0

为什么一个进程在fork时没有到达`exit(0)`?

我有以下程序,只是为了测试我是否理解分叉和共享内存。 总之,它创建共享内存,分叉,分叉,分叉,并在每个分叉中写入数据并退出。 #包括...

回答 1 投票 0

如何减少boost::interprocess::map中创建和插入的时间?

在下面的代码中,我将 msgpack 文件解压到 std::map。这个过程的持续时间几乎是85秒。 #包括 #包括 #包括 #包括 在下面的代码中,我将 msgpack 文件解压到 std::map。这个过程持续时间差不多85秒。 #include <map> #include <vector> #include <string> #include <iostream> #include <exception> #include <msgpack.hpp> #include <boost/variant.hpp> #include <boost/filesystem.hpp> using namespace std::literals; namespace fs = boost::filesystem; enum class TYPE_MSG : int { NULLPTR_, INT64_, DOUBLE_, STRING_, VECTOR_, MAP_, }; class MOVar; typedef boost::variant<std::nullptr_t, int64_t, double, std::string, std::vector<MOVar>, std::map<std::string, MOVar>> MOVarST; class MOVar : public MOVarST { public: MOVar() : MOVarST(nullptr) {} MOVar(double b) { MOVarST::operator=(b); } MOVar(int64_t b) { MOVarST::operator=(b); } MOVar(int b) : MOVar(static_cast<int64_t>(b)) {} MOVar(std::string &&b) { MOVarST::operator=(b); } MOVar(std::vector<MOVar> &b) { MOVarST::operator=(b); } MOVar(std::map<std::string, MOVar> &b) { MOVarST::operator=(b); } const MOVar &operator=(const int64_t &b) { MOVarST::operator=(b); return *this; } const MOVar &operator=(std::string &&b) { MOVarST::operator=(std::move(b)); return *this; } const MOVar &operator=(std::string &b) { MOVarST::operator=(std::move(b)); return *this; } const MOVar &operator=(const double &b) { MOVarST::operator=(b); return *this; } const MOVar &operator=(std::vector<MOVar> &&b) { MOVarST::operator=(std::move(b)); return *this; } const MOVar &operator=(std::map<std::string, MOVar> &&b) { MOVarST::operator=(std::move(b)); return *this; } bool is_map() const { return which() == (int)TYPE_MSG::MAP_; } bool is_int64() const { return which() == (int)TYPE_MSG::INT64_; } bool is_nill() const { return which() == (int)TYPE_MSG::NULLPTR_; } bool is_double() const { return which() == (int)TYPE_MSG::DOUBLE_; } bool is_string() const { return which() == (int)TYPE_MSG::STRING_; } bool is_vector() const { return which() == (int)TYPE_MSG::VECTOR_; } const double &_as_double() const { return boost::get<double>(*this); } const int64_t &_as_int64() const { return boost::get<int64_t>(*this); } const std::string &_as_string() const { return boost::get<std::string>(*this); } const std::vector<MOVar> &_as_vector() const { return boost::get<std::vector<MOVar>>(*this); } const std::map<std::string, MOVar> &_as_map() const { return boost::get<std::map<std::string, MOVar>>(*this); } private: }; void convert_msgpack_to_movar(msgpack::object const &o, MOVar &v); namespace msgpack { MSGPACK_API_VERSION_NAMESPACE(MSGPACK_DEFAULT_API_NS) { namespace adaptor { template <> struct convert<MOVar> { msgpack::object const &operator()(msgpack::object const &o, MOVar &v) const { convert_msgpack_to_movar(o, v); return o; } }; } } } int main() { std::map<std::string, MOVar> map; auto fileName = "big_map.msgpack"s; auto startTime = std::chrono::high_resolution_clock::now(); { std::ifstream file(fileName, std::ios::binary); auto fileSize = fs::file_size(fileName); std::vector<char> buffer(fileSize); file.read(buffer.data(), fileSize); msgpack::object_handle oh = msgpack::unpack(buffer.data(), fileSize); msgpack::object deserialized = oh.get(); deserialized.convert(map); } auto endTime = std::chrono::high_resolution_clock::now(); auto duration = std::chrono::duration_cast<std::chrono::seconds>(endTime - startTime); std::cout << "Duration: " << duration.count() << " seconds" << std::endl; } 但是当我尝试用 std::map 替换 boost::interprocess::map 时,时间几乎增加了 12 倍。 我有什么错吗?是否有必要替换我使用 boost 共享内存的方法? (我在第二个过程中检查了两张地图及其结果,两者的结果都是相同的。) #include <fstream> #include <iostream> #include <exception> #include <msgpack.hpp> #include <boost/variant.hpp> #include <boost/filesystem.hpp> #include <boost/interprocess/containers/map.hpp> #include <boost/interprocess/containers/string.hpp> #include <boost/interprocess/containers/vector.hpp> #include <boost/interprocess/managed_shared_memory.hpp> #include <boost/interprocess/allocators/allocator.hpp> using namespace std::literals; namespace fs = boost::filesystem; namespace bip = boost::interprocess; enum class TYPE_MSG : int { NULLPTR_, INT64_, DOUBLE_, STRING_, VECTOR_, MAP_, }; auto sharedMemoryName = "MySharedMemory"s; unsigned long long shmSize = 9.8 * 1024 * 1024 * 1024ull; bip::managed_shared_memory segment(bip::open_or_create, sharedMemoryName.data(), shmSize); template <typename T> using Alloc = bip::allocator<T, bip::managed_shared_memory::segment_manager>; const Alloc<void> allocator(segment.get_segment_manager()); //MOVar class is like last example void Convertor(MAP &map, std::map<std::string, MOVar>::const_iterator &pair); class MOVarBip; using STR = bip::basic_string<char, std::char_traits<char>, Alloc<char>>; using PAIR = std::pair<const STR, MOVarBip>; using MAP = bip::map<STR, MOVarBip, std::less<STR>, Alloc<PAIR>>; using Vec = bip::vector<MOVarBip, Alloc<MOVarBip>>; typedef boost::variant<std::nullptr_t, int64_t, double, STR, Vec, MAP> MOVarSTBIP; class MOVarBip : public MOVarSTBIP { public: MOVarBip() : MOVarSTBIP(nullptr) {} MOVarBip(int64_t &b) { MOVarSTBIP::operator=(std::move(b)); } MOVarBip(double &b) { MOVarSTBIP::operator=(std::move(b)); } MOVarBip(STR &b) { MOVarSTBIP::operator=(std::move(b)); } MOVarBip(Vec &b) { MOVarSTBIP::operator=(std::move(b)); } MOVarBip(MAP &b) { MOVarSTBIP::operator=(std::move(b)); } const MOVarBip& operator=(int64_t&& b) { MOVarSTBIP::operator=(std::move(b)); return *this; } const MOVarBip& operator=(double&& b) { MOVarSTBIP::operator=(std::move(b)); return *this; } const MOVarBip& operator=(std::string&& b) { auto &tmpValue = *segment.construct<STR>(bip::anonymous_instance)(allocator); tmpValue = b.data(); MOVarSTBIP::operator=(std::move(tmpValue)); return *this; } const MOVarBip& operator=(std::vector<MOVar>&& value) { auto &vecBip = *segment.construct<Vec>(bip::anonymous_instance)(allocator); for (auto &item : value) { switch (item.which()) { case static_cast<int>(TYPE_MSG::MAP_): { auto &mapBip = *segment.construct<MAP>(bip::anonymous_instance)(allocator); auto element = item._as_map().begin(); auto mapEnd = item._as_map().end(); for (; element != mapEnd; ++element) { Convertor(mapBip, element); } MOVarBip valueBip = mapBip; vecBip.push_back(std::move(valueBip)); break; } case static_cast<int>(TYPE_MSG::STRING_): { auto &tmpValue = *segment.construct<STR>(bip::anonymous_instance)(allocator); tmpValue = item._as_string().data(); MOVarBip valueBip = tmpValue; vecBip.push_back(std::move(valueBip)); break; } default: { throw std::logic_error("The code doesn't support this scenario for Vec type!"); } } } MOVarSTBIP::operator=(std::move(vecBip)); return *this; } const MOVarBip& operator=(std::map<std::string, MOVar>&& value) { auto &mapBip = *segment.construct<MAP>(bip::anonymous_instance)(allocator); auto itr = value.cbegin(); auto endPoint = value.cend(); for (; itr != endPoint; ++itr) { Convertor(mapBip, itr); } MOVarSTBIP::operator=(std::move(mapBip)); return *this; } bool is_map() const { return which() == (int)TYPE_MSG::MAP_; } bool is_int64() const { return which() == (int)TYPE_MSG::INT64_; } bool is_nill() const { return which() == (int)TYPE_MSG::NULLPTR_; } bool is_double() const { return which() == (int)TYPE_MSG::DOUBLE_; } bool is_string() const { return which() == (int)TYPE_MSG::STRING_; } bool is_vector() const { return which() == (int)TYPE_MSG::VECTOR_; } const double &_as_double() const { return boost::get<double>(*this); } const int64_t &_as_int64() const { return boost::get<int64_t>(*this); } const STR &_as_string() const { return boost::get<STR>(*this); } const Vec &_as_vector() const { return boost::get<Vec>(*this); } const MAP &_as_map() const { return boost::get<MAP>(*this); } private: }; void Convertor(MAP &map, std::map<std::string, MOVar>::const_iterator &pair) { auto &keyBip = *segment.construct<STR>(bip::anonymous_instance)(allocator); keyBip = pair->first.data(); auto &value = pair->second; switch (value.which()) { case static_cast<int>(TYPE_MSG::NULLPTR_): { auto &valueBip = *segment.construct<MOVarBip>(bip::anonymous_instance)(); map.insert({std::move(keyBip), std::move(valueBip)}); break; } case static_cast<int>(TYPE_MSG::INT64_): { auto &tmpValue = *segment.construct<int64_t>(bip::anonymous_instance)(); tmpValue = value._as_int64(); MOVarBip valueBip = tmpValue; map.insert({std::move(keyBip), std::move(valueBip)}); break; } case static_cast<int>(TYPE_MSG::DOUBLE_): { auto &tmpValue = *segment.construct<double>(bip::anonymous_instance)(); tmpValue = value._as_double(); MOVarBip valueBip = tmpValue; map.insert({std::move(keyBip), std::move(valueBip)}); break; } case static_cast<int>(TYPE_MSG::STRING_): { auto &tmpValue = *segment.construct<STR>(bip::anonymous_instance)(allocator); tmpValue = value._as_string().data(); MOVarBip valueBip = tmpValue; map.insert({std::move(keyBip), std::move(valueBip)}); break; } case static_cast<int>(TYPE_MSG::VECTOR_): { auto &vecBip = *segment.construct<Vec>(bip::anonymous_instance)(allocator); for (auto &item : value._as_vector()) { switch (item.which()) { case static_cast<int>(TYPE_MSG::MAP_): { auto &mapBip = *segment.construct<MAP>(bip::anonymous_instance)(allocator); auto element = item._as_map().begin(); auto mapEnd = item._as_map().end(); for (; element != mapEnd; ++element) { Convertor(mapBip, element); } MOVarBip valueBip = mapBip; vecBip.push_back(std::move(valueBip)); break; } case static_cast<int>(TYPE_MSG::STRING_): { auto &tmpValue = *segment.construct<STR>(bip::anonymous_instance)(allocator); tmpValue = item._as_string().data(); MOVarBip valueBip = tmpValue; vecBip.push_back(std::move(valueBip)); break; } default: { throw std::logic_error("The code doesn't support this scenario for Vec type!"); } } } MOVarBip valueBip = vecBip; map.insert({std::move(keyBip), std::move(valueBip)}); break; } case static_cast<int>(TYPE_MSG::MAP_): { auto &mapBip = *segment.construct<MAP>(bip::anonymous_instance)(allocator); auto itr = value._as_map().begin(); auto endPoint = value._as_map().end(); for (; itr != endPoint; ++itr) { Convertor(mapBip, itr); } MOVarBip valueBip = mapBip; map.insert({std::move(keyBip), std::move(valueBip)}); break; } default: { throw std::logic_error("The code doesn't support this scenario!"); break; } } } namespace msgpack { MSGPACK_API_VERSION_NAMESPACE(MSGPACK_DEFAULT_API_NS) { namespace adaptor { template <> struct convert<STR> { msgpack::object const &operator()(msgpack::object const &o, STR &v) const { switch (o.type) { case msgpack::type::BIN: v.assign(o.via.bin.ptr, o.via.bin.size); break; case msgpack::type::STR: v.assign(o.via.str.ptr, o.via.str.size); break; default: throw msgpack::type_error(); break; } return o; } }; template <> struct convert<MOVarBip> { msgpack::object const &operator()(msgpack::object const &o, MOVarBip &v) const { switch (o.type) { case msgpack::type::NIL: v = MOVarBip(); break; case msgpack::type::BOOLEAN: v = (int64_t)(o.as<bool>()); break; case msgpack::type::POSITIVE_INTEGER: { uint64_t temp = o.as<uint64_t>(); if (temp > (uint64_t)0x7FFFFFFFFFFFFFFF) { v = std::to_string(temp); } else { v = ((int64_t)temp); } break; } case msgpack::type::NEGATIVE_INTEGER: v = (o.as<int64_t>()); break; case msgpack::type::FLOAT32: v = ((double)o.as<float>()); break; case msgpack::type::FLOAT64: v = (o.as<double>()); break; case msgpack::type::STR: v = o.as<std::string>(); break; case msgpack::type::BIN: v = o.as<std::string>(); break; case msgpack::type::ARRAY: v = o.as<std::vector<MOVar>>(); break; case msgpack::type::MAP: v = o.as<std::map<std::string, MOVar>>(); break; case msgpack::type::EXT: throw msgpack::type_error(); break; } return o; } }; template <> struct convert<MAP> { msgpack::object const &operator()(msgpack::object const &o, MAP &v) const { if (o.type != msgpack::type::MAP) { throw msgpack::type_error(); } msgpack::object_kv *p(o.via.map.ptr); msgpack::object_kv *const pend(o.via.map.ptr + o.via.map.size); auto &tmp = *segment.construct<MAP>(bip::anonymous_instance)(allocator); for (; p != pend; ++p) { auto &key = *segment.construct<STR>(bip::anonymous_instance)(allocator); p->key.convert(key); p->val.convert(tmp[std::move(key)]); } v = std::move(tmp); return o; } }; } } } int main() { auto fileName = "big_map.msgpack"s; startTime = std::chrono::high_resolution_clock::now(); { std::ifstream file(fileName, std::ios::binary); auto fileSize = fs::file_size(fileName); std::vector<char> buffer(fileSize); file.read(buffer.data(), fileSize); auto &bip_map = *segment.construct<MAP>("bip_map")(allocator); msgpack::object_handle oh = msgpack::unpack(buffer.data(), fileSize); msgpack::object deserialized = oh.get(); deserialized.convert(bip_map); } endTime = std::chrono::high_resolution_clock::now(); duration = std::chrono::duration_cast<std::chrono::seconds>(endTime - startTime); std::cout << "Duration: " << duration.count() << " seconds" << std::endl; boost::interprocess::shared_memory_object::remove(sharedMemoryName.data()); } 这是代码的输出: 持续时间:72秒(std::map) 持续时间:956秒(boost::interprocess::map) 您通过手动构造匿名实例来否定分配器。这不仅会导致泄漏(您的代码中有大量泄漏),而且效率也较低。 从 MOVar 到 MOVarBip 的所有手动编码转换都可以由单个函数处理,从而避免许多临时操作: template <typename T> void BipConvert(T const& v, MOVarBip& result) { struct Vis { MOVarBip& result; void operator()(MOVar const& v) const { boost::apply_visitor(*this, v); } void operator()(std::nullptr_t) const { result = {}; } void operator()(int64_t v) const { result = v; } void operator()(std::string const& v) const { result = STR(v.c_str(), segment.get_segment_manager()); } void operator()(std::map<std::string, MOVar> const& v) const { result = MAP(segment.get_segment_manager()); for (auto& map = boost::get<MAP>(result); auto& [k, v] : v) BipConvert(v, map.emplace(k).first->second); } void operator()(std::vector<MOVar> const& v) const { result = Vec(segment.get_segment_manager()); for (auto& vec = boost::get<Vec>(result); auto& item : v) BipConvert(item, vec.emplace_back()); } }; Vis{result}(v); } 此外,从可变左值引用中随机移动并不是导致未定义行为错误的秘诀,例如: MOVarBip(STR &b) { MOVarSTBIP::operator=(std::move(b)); } 解决这个问题的最简单方法是按值获取,无论参数的值类别如何,它都会做正确的事情。无论如何,如果您打算支持不同的段,那么除非分配器相等,否则您不应该移动。 简化 反转上述观察,我发现您确实希望有一个引用全局段的全局静态分配器。比如: template <typename T> using BaseAlloc = bip::allocator<T, bip::managed_shared_memory::segment_manager>; template <typename T> struct SegmentAlloc : BaseAlloc<T> { SegmentAlloc(bip::managed_shared_memory::segment_manager* mgr = segment->get_segment_manager()) : BaseAlloc<T>(mgr) {} using BaseAlloc<T>::BaseAlloc; template <typename U> struct rebind { using other = SegmentAlloc<U>; }; }; 现在您可以定义变量类型: struct MOVarBip; using STR = bip::basic_string<char, std::char_traits<char>, SegmentAlloc<char>>; using PAIR = std::pair<const STR, MOVarBip>; using VEC = bip::vector<MOVarBip, SegmentAlloc<MOVarBip>>; using MAP = bip::map<STR, MOVarBip, std::less<STR>, SegmentAlloc<PAIR>>; static void json_dump(MAP const& data, std::string filename); using MOVarSTBIP = boost::variant<std::nullptr_t, int64_t, double, STR, VEC, MAP>; struct MOVarBip : MOVarSTBIP { using Base = MOVarSTBIP; template <typename... Args> explicit MOVarBip(Args&&... args) : Base(std::forward<Args>(args)...) {} using Base::operator=; explicit MOVarBip(std::string_view s) : Base(STR(s.data(), s.size())) {} explicit MOVarBip(std::string s) : Base(STR(s.data(), s.size())) {} bool is_map() const { return which() == TYPE_MSG::MAP_; } bool is_int64() const { return which() == TYPE_MSG::INT64_; } bool is_nill() const { return which() == TYPE_MSG::NULLPTR_; } bool is_double() const { return which() == TYPE_MSG::DOUBLE_; } bool is_string() const { return which() == TYPE_MSG::STRING_; } bool is_vector() const { return which() == TYPE_MSG::VECTOR_; } double const& _as_double() const { return boost::get<double>(*this); } int64_t const& _as_int64() const { return boost::get<int64_t>(*this); } STR const& _as_string() const { return boost::get<STR>(*this); } VEC const& _as_vector() const { return boost::get<VEC>(*this); } MAP const& _as_map() const { return boost::get<MAP>(*this); } double & _as_double() { return boost::get<double>(*this); } int64_t & _as_int64() { return boost::get<int64_t>(*this); } STR & _as_string() { return boost::get<STR>(*this); } VEC & _as_vector() { return boost::get<VEC>(*this); } MAP & _as_map() { return boost::get<MAP>(*this); } }; 无论如何,我总是更喜欢非侵入性的 msgpack 适配,而这里正是它的全部荣耀: namespace msgpack { MSGPACK_API_VERSION_NAMESPACE(MSGPACK_DEFAULT_API_NS) { namespace adaptor { template <> struct convert<STR> { msgpack::object const& operator()(msgpack::object const& o, STR& v) const { switch (o.type) { case msgpack::type::BIN: v.assign(o.via.bin.ptr, o.via.bin.size); break; case msgpack::type::STR: v.assign(o.via.str.ptr, o.via.str.size); break; default: throw msgpack::type_error(); break; } return o; } }; template <> struct convert<MOVarBip> { msgpack::object const& operator()(msgpack::object const& o, MOVarBip& v) const { switch (o.type) { case msgpack::type::NIL: v = MOVarBip(); break; case msgpack::type::BOOLEAN: v = static_cast<int64_t>(o.as<bool>()); break; case msgpack::type::POSITIVE_INTEGER: if (uint64_t temp = o.as<uint64_t>(); temp > 0x7FFFFFFFFFFFFFFF) v = MOVarBip(std::to_string(temp)); else v = static_cast<int64_t>(temp); break; case msgpack::type::NEGATIVE_INTEGER: v = o.as<int64_t>(); break; case msgpack::type::FLOAT32: case msgpack::type::FLOAT64: v = o.as<double>(); break; case msgpack::type::STR: case msgpack::type::BIN: v = o.as<STR>(); break; case msgpack::type::ARRAY: v = o.as<VEC>(); break; case msgpack::type::MAP: v = o.as<MAP>(); break; case msgpack::type::EXT: throw msgpack::type_error(); break; } return o; } }; template <> struct convert<MAP> { msgpack::object const& operator()(msgpack::object const& o, MAP& m) const { if (o.type != msgpack::type::MAP) throw msgpack::type_error(); m.clear(); for (auto p = o.via.map.ptr, pend = p + o.via.map.size; p != pend; ++p) { auto [it, uniqueOk] = m.emplace(p->key.as<STR>(), MOVarBip{}); assert(uniqueOk); p->val.convert(it->second); } return o; } }; template <> struct convert<VEC> { msgpack::object const& operator()(msgpack::object const& o, VEC& v) const { if (o.type != msgpack::type::ARRAY) throw msgpack::type_error(); for (auto p = o.via.array.ptr, pend = p + o.via.array.size; p != pend; ++p) p->convert(v.emplace_back()); return o; } }; } // namespace adaptor } } // namespace msgpack 我认为它可以更加优化,但我希望这是简化的良好开端。 完整演示 实时编译器资源管理器 // #define MSGPACK_USE_BOOST #include <iostream> #include <msgpack.hpp> #include <boost/interprocess/allocators/allocator.hpp> #include <boost/interprocess/containers/map.hpp> #include <boost/interprocess/containers/string.hpp> #include <boost/interprocess/containers/vector.hpp> #include <boost/interprocess/managed_shared_memory.hpp> #include <boost/variant.hpp> using namespace std::literals; namespace bip = boost::interprocess; enum /*class*/ TYPE_MSG : int { NULLPTR_, INT64_, DOUBLE_, STRING_, VECTOR_, MAP_ }; static auto sharedMemoryName = "MySharedMemory"s; static auto shmSize = 9.8 * 1024 * 1024 * 1024ull; static auto segment = std::make_unique<bip::managed_shared_memory>(// bip::open_or_create, sharedMemoryName.data(), shmSize); template <typename T> using BaseAlloc = bip::allocator<T, bip::managed_shared_memory::segment_manager>; template <typename T> struct SegmentAlloc : BaseAlloc<T> { SegmentAlloc(bip::managed_shared_memory::segment_manager* mgr = segment->get_segment_manager()) : BaseAlloc<T>(mgr) {} using BaseAlloc<T>::BaseAlloc; template <typename U> struct rebind { using other = SegmentAlloc<U>; }; }; struct MOVarBip; using STR = bip::basic_string<char, std::char_traits<char>, SegmentAlloc<char>>; using PAIR = std::pair<const STR, MOVarBip>; using VEC = bip::vector<MOVarBip, SegmentAlloc<MOVarBip>>; using MAP = bip::map<STR, MOVarBip, std::less<STR>, SegmentAlloc<PAIR>>; static void json_dump(MAP const& data, std::string filename); using MOVarSTBIP = boost::variant<std::nullptr_t, int64_t, double, STR, VEC, MAP>; struct MOVarBip : MOVarSTBIP { using Base = MOVarSTBIP; template <typename... Args> explicit MOVarBip(Args&&... args) : Base(std::forward<Args>(args)...) {} using Base::operator=; explicit MOVarBip(std::string_view s) : Base(STR(s.data(), s.size())) {} explicit MOVarBip(std::string s) : Base(STR(s.data(), s.size())) {} bool is_map() const { return which() == TYPE_MSG::MAP_; } bool is_int64() const { return which() == TYPE_MSG::INT64_; } bool is_nill() const { return which() == TYPE_MSG::NULLPTR_; } bool is_double() const { return which() == TYPE_MSG::DOUBLE_; } bool is_string() const { return which() == TYPE_MSG::STRING_; } bool is_vector() const { return which() == TYPE_MSG::VECTOR_; } double const& _as_double() const { return boost::get<double>(*this); } int64_t const& _as_int64() const { return boost::get<int64_t>(*this); } STR const& _as_string() const { return boost::get<STR>(*this); } VEC const& _as_vector() const { return boost::get<VEC>(*this); } MAP const& _as_map() const { return boost::get<MAP>(*this); } double & _as_double() { return boost::get<double>(*this); } int64_t & _as_int64() { return boost::get<int64_t>(*this); } STR & _as_string() { return boost::get<STR>(*this); } VEC & _as_vector() { return boost::get<VEC>(*this); } MAP & _as_map() { return boost::get<MAP>(*this); } }; namespace msgpack { MSGPACK_API_VERSION_NAMESPACE(MSGPACK_DEFAULT_API_NS) { namespace adaptor { template <> struct convert<STR> { msgpack::object const& operator()(msgpack::object const& o, STR& v) const { switch (o.type) { case msgpack::type::BIN: v.assign(o.via.bin.ptr, o.via.bin.size); break; case msgpack::type::STR: v.assign(o.via.str.ptr, o.via.str.size); break; default: throw msgpack::type_error(); break; } return o; } }; template <> struct convert<MOVarBip> { msgpack::object const& operator()(msgpack::object const& o, MOVarBip& v) const { switch (o.type) { case msgpack::type::NIL: v = MOVarBip(); break; case msgpack::type::BOOLEAN: v = static_cast<int64_t>(o.as<bool>()); break; case msgpack::type::POSITIVE_INTEGER: if (uint64_t temp = o.as<uint64_t>(); temp > 0x7FFFFFFFFFFFFFFF) v = MOVarBip(std::to_string(temp)); else v = static_cast<int64_t>(temp); break; case msgpack::type::NEGATIVE_INTEGER: v = o.as<int64_t>(); break; case msgpack::type::FLOAT32: case msgpack::type::FLOAT64: v = o.as<double>(); break; case msgpack::type::STR: case msgpack::type::BIN: v = o.as<STR>(); break; case msgpack::type::ARRAY: v = o.as<VEC>(); break; case msgpack::type::MAP: v = o.as<MAP>(); break; case msgpack::type::EXT: throw msgpack::type_error(); break; } return o; } }; template <> struct convert<MAP> { msgpack::object const& operator()(msgpack::object const& o, MAP& m) const { if (o.type != msgpack::type::MAP) throw msgpack::type_error(); m.clear(); for (auto p = o.via.map.ptr, pend = p + o.via.map.size; p != pend; ++p) { auto [it, uniqueOk] = m.emplace(p->key.as<STR>(), MOVarBip{}); assert(uniqueOk); p->val.convert(it->second); } return o; } }; template <> struct convert<VEC> { msgpack::object const& operator()(msgpack::object const& o, VEC& v) const { if (o.type != msgpack::type::ARRAY) throw msgpack::type_error(); for (auto p = o.via.array.ptr, pend = p + o.via.array.size; p != pend; ++p) p->convert(v.emplace_back()); return o; } }; } // namespace adaptor } } // namespace msgpack #include <chrono> #include <fstream> static constexpr auto now = std::chrono::high_resolution_clock::now; static void timed_load(std::string filename, MAP& into) { auto startTime = now(); std::ifstream file(filename, std::ios::binary); std::vector<char> const buffer(std::istreambuf_iterator<char>(file), {}); msgpack::object_handle oh = msgpack::unpack(buffer.data(), buffer.size()); msgpack::object const& deserialized = oh.get(); deserialized.convert(into); std::cout << "Duration: " << (now() - startTime) / 1ms << "ms" << std::endl; } int main() { { auto& bip_map = *segment->find_or_construct<MAP>("bip_map")(); timed_load("big_map.msgpack", bip_map); json_dump(bip_map, "big_map.json"); } segment.reset(); // close before remove bip::shared_memory_object::remove(sharedMemoryName.c_str()); } #include <boost/json.hpp> void json_dump(MAP const& data, std::string filename) { struct Vis { using value = boost::json::value; value operator()(MOVarBip const& var) const { return boost::apply_visitor(*this, var); } value operator()(std::nullptr_t) const { return nullptr; } value operator()(int64_t i) const { return i; } value operator()(double d) const { return d; } value operator()(STR const& s) const { return s.c_str(); } value operator()(VEC const& v) const { boost::json::array arr; for (auto& el : v) arr.push_back((*this)(el)); return arr; } value operator()(MAP const& m) const { boost::json::object obj; for (auto& [k, v] : m) obj[k.c_str()] = (*this)(v); return obj; } }; std::ofstream(filename) << Vis{}(data); } 我已经确认在 ASAN/UBSAN 下它是干净的并且无泄漏。正如您所看到的,我抛出一个 json 转储只是为了验证数据是否可访问且有效。 在我的机器上: 总结 我想这可能是进一步优化的良好基础,例如与您已经找到的 reserve() 一起。

回答 1 投票 0

--Nextflow 管道中 Docker 的 shm_size 更改:containerOptions 似乎不起作用

我正在尝试增加用于运行 Nextflow 管道的 Docker 映像的共享内存大小。根据网上的一些指示,我已将以下内容添加到我的配置文件中: 码头工人{ 恩...

回答 1 投票 0

我应该如何在共享内存中初始化pthread互斥体,因为在程序启动时它们已经可以初始化了?

我正在使用共享的、强大的pthread互斥体来保护我的应用程序中的一些共享内存区域。由于我的程序是由 systemd 服务管理的,因此它可能会重新启动,其中......

回答 1 投票 0

© www.soinside.com 2019 - 2024. All rights reserved.