如何将项目从 boost::variant 移动到多地图?
How do I move items from a boost::variant to a multimap?
我想通过使用移动而不是复制来提高下面代码中 PickPotatoes
的性能,但我不知道如何使用 insert
和 boost::variant
。在我的实际用例中,解析数据大约需要 75% 的时间,而真实版本的 PickPotatoes 大约需要 25%,由于一些慢副本。通过改进 PickPotatoes
我应该能够降低它。是否可以从 boost::variant
中移出某些内容并改进 PickPotatoes
?
#include <map>
#include "boost/variant.hpp"
#include <string>
#include <vector>
#include <functional>
struct tuber
{
int z;
std::vector<double> r;
};
int getZ(const tuber& t)
{
return t.z;
}
boost::variant<std::string, tuber> GrowPotato()
{
int z = std::rand() / (RAND_MAX / 10);
if (z < 2)
{
return "BAD POTATO";
}
else
{
tuber ret;
ret.z = z;
ret.r.resize(10000);
for (int i = 0;i < 10000;++i)
{
ret.r[i] = std::rand() / (RAND_MAX / 50);
}
return ret;
}
}
std::vector<boost::variant<std::string,tuber>> GrowPotatoes(int n)
{
std::vector<boost::variant<std::string, tuber>> ret;
ret.resize(n);
for (int i = 0; i < n; ++i)
{
ret[i] = GrowPotato();
}
return ret;
}
//could make this more efficient.
std::pair<std::vector<std::string>,std::multimap<int, tuber>> PickPotatoes(std::vector <boost::variant<std::string, tuber>> result)
{
std::pair<std::vector<std::string>,std::multimap<int,tuber>> ret;
int numTypTwo = 0;
for (const auto& item : result)
{
numTypTwo += item.which();
}
ret.first.resize(result.size() - numTypTwo);
int fstSpot = 0;
for (int i = 0; i < result.size();++i)
{
if (result[i].which())
{
ret.second.insert(std::pair<int, tuber>(getZ(boost::get<tuber>(result[i])), boost::get<tuber>(result[i])));
}
else
{
ret.first[fstSpot++] = std::move(boost::get<std::string>(result[i]));
}
}
return ret;
}
int main()
{
std::srand(0);
std::vector<boost::variant<std::string, tuber>> q= GrowPotatoes(5000);
std::pair<std::vector<std::string>, std::multimap<int, tuber>> z = PickPotatoes(q);
return 0;
}
最简单的获胜方法是移动参数值:
std::pair<std::vector<std::string>, std::multimap<int, tuber>> z = PickPotatoes(std::move(q));
的确,它赢得了 14% 的性能,大致在我的基准测试中。其余部分在很大程度上取决于它的全部含义,以及它将如何使用。
专注于减少分配(如果可以,请使用非基于节点的容器,例如 boost::flat_multimap
,明确排序,使用 string_view,解析为所需的数据结构而不是中间结构)。
奖金
我使用以下方法剃掉了大约 30%:
std::pair<std::vector<std::string>, std::multimap<int, tuber> >
PickPotatoes(std::vector<boost::variant<std::string, tuber> >&& result) {
std::pair<std::vector<std::string>, std::multimap<int, tuber> > ret;
ret.first.reserve(result.size());
struct Vis {
using result_type = void;
void operator()(std::string& s) const {
first.emplace_back(std::move(s));
}
void operator()(tuber& tbr) const {
second.emplace(tbr.z, std::move(tbr));
}
std::vector<std::string>& first;
std::multimap<int, tuber>& second;
} visitor { ret.first, ret.second };
for (auto& element : result) {
boost::apply_visitor(visitor, element);
}
return ret;
}
使用 emplace,避免重复 get<>
,避免循环获取 first
大小等
我想通过使用移动而不是复制来提高下面代码中 PickPotatoes
的性能,但我不知道如何使用 insert
和 boost::variant
。在我的实际用例中,解析数据大约需要 75% 的时间,而真实版本的 PickPotatoes 大约需要 25%,由于一些慢副本。通过改进 PickPotatoes
我应该能够降低它。是否可以从 boost::variant
中移出某些内容并改进 PickPotatoes
?
#include <map>
#include "boost/variant.hpp"
#include <string>
#include <vector>
#include <functional>
struct tuber
{
int z;
std::vector<double> r;
};
int getZ(const tuber& t)
{
return t.z;
}
boost::variant<std::string, tuber> GrowPotato()
{
int z = std::rand() / (RAND_MAX / 10);
if (z < 2)
{
return "BAD POTATO";
}
else
{
tuber ret;
ret.z = z;
ret.r.resize(10000);
for (int i = 0;i < 10000;++i)
{
ret.r[i] = std::rand() / (RAND_MAX / 50);
}
return ret;
}
}
std::vector<boost::variant<std::string,tuber>> GrowPotatoes(int n)
{
std::vector<boost::variant<std::string, tuber>> ret;
ret.resize(n);
for (int i = 0; i < n; ++i)
{
ret[i] = GrowPotato();
}
return ret;
}
//could make this more efficient.
std::pair<std::vector<std::string>,std::multimap<int, tuber>> PickPotatoes(std::vector <boost::variant<std::string, tuber>> result)
{
std::pair<std::vector<std::string>,std::multimap<int,tuber>> ret;
int numTypTwo = 0;
for (const auto& item : result)
{
numTypTwo += item.which();
}
ret.first.resize(result.size() - numTypTwo);
int fstSpot = 0;
for (int i = 0; i < result.size();++i)
{
if (result[i].which())
{
ret.second.insert(std::pair<int, tuber>(getZ(boost::get<tuber>(result[i])), boost::get<tuber>(result[i])));
}
else
{
ret.first[fstSpot++] = std::move(boost::get<std::string>(result[i]));
}
}
return ret;
}
int main()
{
std::srand(0);
std::vector<boost::variant<std::string, tuber>> q= GrowPotatoes(5000);
std::pair<std::vector<std::string>, std::multimap<int, tuber>> z = PickPotatoes(q);
return 0;
}
最简单的获胜方法是移动参数值:
std::pair<std::vector<std::string>, std::multimap<int, tuber>> z = PickPotatoes(std::move(q));
的确,它赢得了 14% 的性能,大致在我的基准测试中。其余部分在很大程度上取决于它的全部含义,以及它将如何使用。
专注于减少分配(如果可以,请使用非基于节点的容器,例如 boost::flat_multimap
,明确排序,使用 string_view,解析为所需的数据结构而不是中间结构)。
奖金
我使用以下方法剃掉了大约 30%:
std::pair<std::vector<std::string>, std::multimap<int, tuber> >
PickPotatoes(std::vector<boost::variant<std::string, tuber> >&& result) {
std::pair<std::vector<std::string>, std::multimap<int, tuber> > ret;
ret.first.reserve(result.size());
struct Vis {
using result_type = void;
void operator()(std::string& s) const {
first.emplace_back(std::move(s));
}
void operator()(tuber& tbr) const {
second.emplace(tbr.z, std::move(tbr));
}
std::vector<std::string>& first;
std::multimap<int, tuber>& second;
} visitor { ret.first, ret.second };
for (auto& element : result) {
boost::apply_visitor(visitor, element);
}
return ret;
}
使用 emplace,避免重复 get<>
,避免循环获取 first
大小等