如何为大量数据生成hashmap
How to generate a hashmap for huge chunk of data?
我想创建一个映射,使一组指针指向动态大小的数组。我确实使用了哈希和链。但由于我使用它的数据是巨大的,程序在几次迭代后给出std::bad_alloc
。其原因可能是new
用于生成链表。
有人建议我应该使用哪种数据结构吗?或者其他可以改善哈希表内存使用的方法?
程序是c++编写的。
这是我的代码看起来像:初始化哈希表:
class Link
{
public:
double iData;
Link* pNext;
Link(double it) : iData(it)
{ }
void displayLink()
{ cout << iData << " "; }
};
class List
{
private:
Link* pFirst;
public:
List()
{ pFirst = NULL; }
void insert(double key)
{
if(pFirst==NULL)
pFirst = new Link(key);
else
{
Link* pLink = new Link(key);
pLink->pNext = pFirst;
pFirst = pLink;
}
}
};
class HashTable
{
public:
int arraySize;
vector<List*> hashArray;
HashTable(int size)
{
hashArray.resize(size);
for(int j=0; j<size; j++)
hashArray[j] = new List;
}
};
主要代码片段:
int t_sample = 1000;
for(int i=0; i < k; i++) // initialize random position
{
x[i] = (cal_rand() * dom_sizex); //dom_sizex = 20e-10 cal_rand() generates rand no between 0 and 1
y[i] = (cal_rand() * dom_sizey); //dom_sizey = 10e-10
}
for(int t=0; t < t_sample; t++)
{
int size;
size = cell_nox * cell_noy; //size of hash table cell_nox = 212, cell_noy = 424
HashTable theHashTable(size); //make table
int hashValue = 0;
for(int n=0; n<k; n++) // k = 10*212*424
{
int m = x[n] /cell_width; //cell_width = 4.7e-8
int l = y[n] / cell_width;
hashValue = (kx*l)+m;
theHashTable.hashArray[hashValue]->insert(n);
}
-------
-------
}
首先,使用标准容器。在您的特定情况下,您可能需要:
-
std::unordered_multimap<int, double>
- 或
std::unordered_map<int, std::vector<double>>
(注意:如果你没有c++ 11,可以在Boost中使用)
你的主循环变成(使用第二个选项):
typedef std::unordered_map<int, std::vector<double>> HashTable;
for(int t = 0; t < t_sample; ++t)
{
size_t const size = cell_nox * cell_noy;
// size of hash table cell_nox = 212, cell_noy = 424
HashTable theHashTable;
theHashTable.reserve(size);
for (int n = 0; n < k; ++n) // k = 10*212*424
{
int m = x[n] / cell_width; //cell_width = 4.7e-8
int l = y[n] / cell_width;
int const cellId = (kx*l)+m;
theHashTable[cellId].push_back(n);
}
}
这将不会泄漏内存(可靠地),尽管当然您可能有其他泄漏,因此将为您提供可靠的基线。它也可能比你的方法更快,有一个更方便的界面,等等。
一般来说,你不应该重新发明轮子,除非你有一个特定的需要,而现有的轮子不能满足你的需求,或者你实际上是在学习如何创造一个轮子,或者创造一个更好的轮子。
操作系统必须解决与内存页面相同的问题,也许值得看看这是如何完成的?首先,让我们假设所有页面都在磁盘上。页是固定大小的内存块。对于您的用例,假设它是记录的数组。因为RAM是有限的,所以操作系统维护一个页码和它在RAM中的位置之间的映射。
那么,假设您的页面有1000条记录,并且您想访问记录2024,您将向操作系统请求第2页,并从该页读取记录24。这样,你的地图大小只有1/1000。
现在,如果您的页面没有映射到内存位置,那么它要么在磁盘上,要么以前从未被访问过(为空)。然后您需要换出另一个页面,并从磁盘加载该页(并更新位置映射)。
这是对发生的事情的一个非常简单的描述,如果有人这样描述我,我不会感到惊讶。
关键是:
这对你意味着什么?
首先,你的数据超过了你的RAM——如果你不想先尝试压缩,你就无法避免写入磁盘。其次,如果您愿意,您的链可以作为页面工作,但我想知道仅仅分页您的哈希码是否会更好。我的意思是,使用上面的位作为页码,下面的位作为页面中的偏移量。避免冲突仍然是关键,因为您希望加载尽可能少的页面。您仍然可以链接页面,最终得到一个小得多的地图。第二,最关键的部分是决定要换掉哪些页面来为新页面腾出空间。LRU应该没问题。如果您能更好地预测哪些页面需要(不需要),那就更好了。第三,你需要页面占位符来告诉你它们是在内存中还是在磁盘上。
- 防止主数据类型C++的隐式转换
- 用于访问容器<T>数据成员的正确 API
- 嵌套在类中时无法设置成员数据
- 使用流处理接收到的数据
- 静态数据成员的问题-修复链接错误会导致编译器错误
- 处理小于cpu数据总线的数据类型.(c++转换为机器代码)
- 在cuda线程之间共享大量常量数据
- C++将文本文件中的数据读取到结构数组中
- 如何在C++中序列化结构数据
- 在C++中打印指向不同基元数据类型的指针的内存地址
- 通过套接字[TCP]传输数据 如何在C / C ++中打包多个整数并使用send() recv()传输数据
- 在c代码之间共享数据的最佳方式
- 链表,反向函数,数据结构
- 数据成员SFINAE的C++17测试:gcc vs clang
- C++浮点数据类型和字符串数据类型无法子到模板函数中
- 如何对点云数据进行排序
- 从矢量<无符号字符>转换为字符* 包括垃圾数据
- 如何为大量数据生成hashmap
- STL有hashmap数据结构吗?
- c++ (Hashmap风格)数据结构非常适合这个场景