占用大量 space 的无序地图
Unordered map taking lot of space
我创建了一张 unit64_t 到 uint64_t 的地图。这是我为评估 space 复杂性而编写的代码:
#include <bits/stdc++.h>
#include "sparsehash/internal/sparseconfig.h"
#include "sparsehash/sparse_hash_map"
using namespace std;
int main(int argc, char *argv[]){
std::string input,reference;
while (getline(cin,input)) {
reference += input;
input.clear();
}
cout<<"length of reference = "<<reference.length()<<endl;
unordered_map<uint64_t, uint64_t> m;
//google::sparse_hash_map<uint64_t, pair<short,long>> m;
for (auto it = reference.begin(); it != reference.end(); it++) {
m[it-reference.begin()]= it-reference.begin();
}
return 0;
}
当我 运行 使用 /usr/bin/time 时,这是程序产生的输出:
length of reference = 4641652
Command being timed: "./a.out"
User time (seconds): 2.97
System time (seconds): 0.15
Percent of CPU this job got: 99%
Elapsed (wall clock) time (h:mm:ss or m:ss): 0:03.13
Average shared text size (kbytes): 0
Average unshared data size (kbytes): 0
Average stack size (kbytes): 0
Average total size (kbytes): 0
Maximum resident set size (kbytes): 251816
Average resident set size (kbytes): 0
Major (requiring I/O) page faults: 0
Minor (reclaiming a frame) page faults: 68259
Voluntary context switches: 1
Involuntary context switches: 104
Swaps: 0
File system inputs: 0
File system outputs: 0
Socket messages sent: 0
Socket messages received: 0
Signals delivered: 0
Page size (bytes): 4096
Exit status: 0
无序地图似乎占用了 250MB space。这似乎异常高。为什么会这样。同样的代码加上google稀疏散列只需要89MB的space,比较合理。
我不明白为什么C++无序映射占用这么多space?
您有 4641652
个条目。所以总的原始数据大小是 4641652*2*8 byte ~= 74 MB
。
关于 hash-tables 有一个重要的事实。 fast hashtables有很多hash buckets,hash-tables有少量hash buckets很慢。
基本上都归结为哈希冲突。如果你有很多散列桶(并且你有一个很好的散列函数),那么散列冲突就很少发生。因此查找真的非常快。
另一方面,如果您的 table 很小(哈希桶不多),那么哈希冲突会经常发生。因此查找功能要慢得多。
现在 std::unordered_map
被人为地设计为快速散列-table,因此它有相当多的开销。哈希桶比条目多得多。在这种情况下,开销约为 250 / 74 ~= 3.3x
,这似乎很正常。
但是 sparsehash
旨在尽可能减少开销(每个条目大约 2 位)。但这当然意味着它要慢得多。
如果您使用散列映射,您应该始终考虑,如果您想要速度或内存效率。
我创建了一张 unit64_t 到 uint64_t 的地图。这是我为评估 space 复杂性而编写的代码:
#include <bits/stdc++.h>
#include "sparsehash/internal/sparseconfig.h"
#include "sparsehash/sparse_hash_map"
using namespace std;
int main(int argc, char *argv[]){
std::string input,reference;
while (getline(cin,input)) {
reference += input;
input.clear();
}
cout<<"length of reference = "<<reference.length()<<endl;
unordered_map<uint64_t, uint64_t> m;
//google::sparse_hash_map<uint64_t, pair<short,long>> m;
for (auto it = reference.begin(); it != reference.end(); it++) {
m[it-reference.begin()]= it-reference.begin();
}
return 0;
}
当我 运行 使用 /usr/bin/time 时,这是程序产生的输出:
length of reference = 4641652
Command being timed: "./a.out"
User time (seconds): 2.97
System time (seconds): 0.15
Percent of CPU this job got: 99%
Elapsed (wall clock) time (h:mm:ss or m:ss): 0:03.13
Average shared text size (kbytes): 0
Average unshared data size (kbytes): 0
Average stack size (kbytes): 0
Average total size (kbytes): 0
Maximum resident set size (kbytes): 251816
Average resident set size (kbytes): 0
Major (requiring I/O) page faults: 0
Minor (reclaiming a frame) page faults: 68259
Voluntary context switches: 1
Involuntary context switches: 104
Swaps: 0
File system inputs: 0
File system outputs: 0
Socket messages sent: 0
Socket messages received: 0
Signals delivered: 0
Page size (bytes): 4096
Exit status: 0
无序地图似乎占用了 250MB space。这似乎异常高。为什么会这样。同样的代码加上google稀疏散列只需要89MB的space,比较合理。
我不明白为什么C++无序映射占用这么多space?
您有 4641652
个条目。所以总的原始数据大小是 4641652*2*8 byte ~= 74 MB
。
关于 hash-tables 有一个重要的事实。 fast hashtables有很多hash buckets,hash-tables有少量hash buckets很慢。
基本上都归结为哈希冲突。如果你有很多散列桶(并且你有一个很好的散列函数),那么散列冲突就很少发生。因此查找真的非常快。 另一方面,如果您的 table 很小(哈希桶不多),那么哈希冲突会经常发生。因此查找功能要慢得多。
现在 std::unordered_map
被人为地设计为快速散列-table,因此它有相当多的开销。哈希桶比条目多得多。在这种情况下,开销约为 250 / 74 ~= 3.3x
,这似乎很正常。
但是 sparsehash
旨在尽可能减少开销(每个条目大约 2 位)。但这当然意味着它要慢得多。
如果您使用散列映射,您应该始终考虑,如果您想要速度或内存效率。