【发布时间】:2021-03-09 20:10:31
【问题描述】:
在我的代码中,我存储了地图中不同组之间交互的参数集。目前在启动时,我添加了每个结构(下面代码中的testvals),其中的键是通过将两个组名连接成一个字符串而创建的。
string nKey = key1;
nKey += JOIN_STRING;
nKey += key2;
map< string, struct> mymap_string;
mymap_string.insert( make_pair(nKey, testval ));
在查找两个组的数据时,我再次创建该字符串,然后使用地图上的查找来检索我的数据。
string nKey = key1;
nKey += JOIN_STRING;
nKey += key2;
auto it = mymap_string.find( nKey );
if ( it != mymap_string.end() )
{
struct vals= it->second;
}
在我的代码中,我在启动时创建了一次地图,但查找部分进行了数百万次。我想知道是否有更好的方法来执行此操作,因为字符串连接似乎相对昂贵,并且 find 可能不是搜索和比较字符串的最快方法?
我的测试似乎表明字符串比使用std::pair<string1, string2> 作为地图的键更快。我看过map 和unordered_map,但似乎没有太大区别。 unordered_map 可能在键数较多的情况下会稍微快一些。
有没有人对什么可能是更好、更快的方法有任何建议?鉴于对此进行的调用次数,如果我可以显着加快速度,我可以节省大量时间。我不介意插入或设置是否不是非常快,因为它只发生一次,但查找很重要。最好使用适用于 Windows 和 Linux 的标准。
更新:
好的,所以从问题来看,似乎需要更多背景信息。
testvals 是当前正在使用的模型的输入参数的双精度结构,其中提供的变量数量将随模型而变化。但通常这在 4-10 个值之间。此处显示了一个典型的集合:
typedef struct
{
double m_temp_min;
double m_temp_max;
double m_liquid_content;
double m_growth_rate;
double m_alpha;
double m_beta;
} testvals;
Key1 和 Key2 始终是从程序核心模块传递的字符串,但这些字符串是用户定义的,这意味着它们可以是从 "a" 到 "my_big_yellow_submarine_3" 的任何字符串。
映射中的键数将取决于数据中的组数。如果只有两组需要提供交互参数,则映射将只有 4 个唯一的字符串键:group1~~group1、group1~~group2、group2~~group1 和 group2~~group2。通常地图中有 3 或 4 个组类型,因此键的数量通常为数十个。这个大小可能是我看不到map 和unordered_map 性能差异很大的原因。
其中一个 cmets 提到了 std::pair<std::string,std::string>,正如我最初所说,调用 make_pair() 的成本似乎远高于制作字符串的成本,并且在我测试时慢了 50% 以上。但我没有尝试std::pair 与unordered_map 的组合。我假设如果 std::pair 使用 map 速度较慢,那么使用 unordered_map 也会更慢。是否有理由期望它会大不相同?
我希望这有助于澄清一些事情。
【问题讨论】:
-
请贴出
testval的struct type的定义。struct有多大?您是在地图中按值存储它还是存储指针/引用?key1和key2究竟采用了哪些类型的值? -
我会尝试为键定义一个自定义类型,以及一个严格的弱排序比较器,以便有效地使用两个离散字符串作为键。为了获得额外的荣誉,该键将包含一个包含
std::reference_wrapper的std::variant,以便可以构建一个用于查找目的的临时键,而无需复制字符串。 -
unordered_map将比map快,因为内部表示是O(1)查找的哈希表(假设有足够的容量和负载因子),而map通常是某种形式的搜索-tree,即O( log n )用于查找。unordered_map,在理论上(和实践中)应该总是比map更快的查找 - 所以如果map更快,那么就会发生一些低效的事情。如何查找您的密钥。 -
@Slava 你读过完整的问题吗?
-
@jpmorr 关于这个你可能会考虑的最后一个想法。当您有字符串的有序映射时,将使用字符串比较操作,它会进行字典排序。因此,为了遍历映射以找到正确的键,它必须遍历字符串,直到字符不匹配。由于您不关心排序,您可以使用自己的比较器首先检查字符串长度,然后检查它们的内容。它可能会有所帮助。无序映射对您来说并不快的原因可能与此有关:它总是需要遍历整个字符串来计算其哈希值。
标签: c++ dictionary associative-array