Статья в wikipedia в r-squareds предполагает, что она может использоваться для подгонки общей модели, а не только для линейной регрессии.
После некоторых исследований и испытаний я нашел решение, приведенное ниже. Ключевым моментом здесь является использование boost::move
(или, возможно, std :: move, не знаю, будет ли здесь разница). Поскольку мы используем boost::move
, не будет копий объектов IPCString
и, следовательно, не нужно умножать на 2
. Помните, из-за того, как мы определили IPCString
, он будет размещен внутри сегмента разделяемой памяти.
Необходимы дополнительные издержки (возможно, из-за выравнивания или других добавленных накладных расходов, или обоих), но всегда остается некоторое пространство. Поскольку я мог посылать несколько мегабайт, служебные данные 500
байтов довольно малы.
Я использую метод std::string
size()
, потому что он возвращает размер строки в байтах .
Код выглядит следующим образом:
shared_memory.h:
#pragma once
#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/interprocess/containers/vector.hpp>
#include <boost/interprocess/containers/string.hpp>
#include <boost/interprocess/allocators/allocator.hpp>
#include <boost/interprocess/sync/named_mutex.hpp>
#include <string>
#include <vector>
#include <exception>
namespace apl_shared_memory
{
typedef boost::interprocess::allocator<char, boost::interprocess::managed_shared_memory::segment_manager> CharAllocator;
typedef boost::interprocess::basic_string<char, std::char_traits<char>, CharAllocator> IPCString;
typedef boost::interprocess::allocator<IPCString, boost::interprocess::managed_shared_memory::segment_manager> StringAllocator;
typedef boost::interprocess::vector<IPCString, StringAllocator> ShmVector;
bool write_to_memory(std::string wsuid, std::string loop_val, std::string should_intercept, std::string post_data) ;
const std::string shm_prefix = "shm_";
const std::string mutex_prefix = "mtx_";
}
shared_memory.cpp:
#include "shared_memory.h"
#include "logger.h"
namespace apl_shared_memory
{
bool write_to_memory(std::string wsuid, std::string loop_val, std::string should_intercept, std::string post_data)
{
bool ret_val;
std::string shm_name = shm_prefix + wsuid;
std::string mtx_name = mutex_prefix + wsuid;
boost::interprocess::named_mutex named_mtx{ boost::interprocess::open_or_create, mtx_name.c_str() };
// Add the size of all the structures we're putting in the shared memory region and add some for the overhead.
size_t size = (3*sizeof(IPCString) + loop_val.size() + should_intercept.size() + post_data.size() + sizeof(ShmVector)) + 500;
try
{
named_mtx.lock();
boost::interprocess::shared_memory_object::remove(shm_name.c_str());
boost::interprocess::managed_shared_memory segment(boost::interprocess::create_only, shm_name.c_str(), size);
CharAllocator charallocator(segment.get_segment_manager());
StringAllocator stringallocator(segment.get_segment_manager());
IPCString shm_loop_val(charallocator);
IPCString shm_should_intercept(charallocator);
IPCString shm_intercepted_data(charallocator);
shm_loop_val = loop_val.c_str();
shm_should_intercept = should_intercept.c_str();
shm_intercepted_data = post_data.c_str();
segment.destroy<ShmVector>("ShmVector");
ShmVector *shmVector = segment.construct<ShmVector>("ShmVector")(stringallocator);
shmVector->clear();
shmVector->reserve(3);
// push_back will call a copy-constructor. But, if we send a rvalue reference (i.e. if we move it), there will be no copying.
shmVector->push_back(boost::move(shm_loop_val));
shmVector->push_back(boost::move(shm_should_intercept));
shmVector->push_back(boost::move(shm_intercepted_data));
ret_val = true;
}
catch (const std::exception& ex)
{
ret_val = false;
boost::interprocess::shared_memory_object::remove(shm_name.c_str());
}
named_mtx.unlock();
return ret_val;
}
}
[1117 ] Если кто-то считает, что я сделал что-то не так, пожалуйста, прокомментируйте.
Вы делаете много предположений об эквивалентности размеров шрифта. Использование памяти строки AC не совпадает с использованием памяти std :: string, которое не совпадает с использованием памяти IPCString, которая на самом деле является вектором , так что вас это не интересует по размеру или длине, но вместимости.
Оцените свои компоненты изо рта лошади: возьмите sizeof
из переменных IPCString
вместо std::string
переменных, а также возьмите shm_loop_val.capacity() + shm_should_intercept.capacity() + shm_intercepted_data.capacity()
вместо определения размера std::strings
!
Вы должно быть ближе к:
size_t size = (3 * sizeof(IPCString) + sizeof(ShmVector) + shm_loop_val.capacity() +
shm_should_intercept.capacity() + shm_intercepted_data.capacity();
Реализация Boost может также выровнять ваши данные по словам, но я начинаю понимать, что это очень маловероятно. Это выглядит как сериализованное. Мы можем посмотреть, что у вас все еще есть проблемы.