C++ 如何为大量数据生成hashmap?
我想制作一个映射,使一组指针指向动态大小的数组。 我确实使用了哈希和链接。但由于我使用它处理的数据非常庞大,程序经过几次迭代后给出了C++ 如何为大量数据生成hashmap?,c++,data-structures,hashtable,C++,Data Structures,Hashtable,我想制作一个映射,使一组指针指向动态大小的数组。 我确实使用了哈希和链接。但由于我使用它处理的数据非常庞大,程序经过几次迭代后给出了std::bad_alloc。其原因可能是用来生成链表的new 有人建议我应该使用哪种数据结构吗? 或者其他任何可以提高哈希表内存使用率的东西 程序是C++的。p> 这就是我的代码的样子: 哈希表的初始化: class Link { public: double iData; Link* pNext;
std::bad_alloc
。其原因可能是用来生成链表的new
有人建议我应该使用哪种数据结构吗?
或者其他任何可以提高哈希表内存使用率的东西
程序是C++的。p> 这就是我的代码的样子: 哈希表的初始化:
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;
}
};
类链接
{
公众:
双盲;
链接*pNext;
链接(双it):iData(it)
{ }
void displayLink()
{cout操作系统必须解决与内存页相同的问题,也许值得一看如何做到这一点?首先,让我们假设所有页都在磁盘上。一个页是一个固定大小的内存块。对于您的用例,让我们假设它是一个记录数组。由于RAM有限,操作系统在页号和内存块之间保持映射内存中的位置
所以,假设你的页面有1000条记录,如果你想访问记录2024,你可以向操作系统请求第2页,然后从该页面读取记录24。这样,你的地图大小只有1/1000
现在,如果您的页面没有到内存位置的映射,那么它要么在磁盘上,要么以前从未被访问过(为空)。然后您需要交换另一个页面,并从磁盘加载该页面(并更新位置映射)
这是对发生的事情的一个非常简单的描述,如果有人这样描述它,我不会感到惊讶
重点是:
这对你意味着什么
首先,您的数据超过了RAM—如果您不想先尝试压缩,您将无法写入磁盘。
第二,如果您愿意,您的链可以用作页面,但我想知道是否只分页您的哈希代码会更好。我的意思是,在页面中使用高位作为页码,使用低位作为偏移量。避免冲突仍然是关键,因为您希望加载尽可能少的页面。您仍然可以链接您的页面,并最终得到一个非常小的页面地图。
第二,一个关键的部分是决定换出哪些页面来为新页面腾出空间。LRU应该可以。如果你能更好地预测你将(不)需要哪些页面,那么对你来说就更好了。
第三,页面需要占位符来告诉您它们是在内存中还是在磁盘上
希望这有帮助。首先,使用标准容器。在您的特定情况下,您可能需要:
std::无序\u多重映射
- 或
std::无序地图
(注意:如果您没有C++11,可以在Boost中使用)
主循环变为(使用第二个选项):
typedef std::无序映射哈希表;
对于(int t=0;t
这不会(可靠地)泄漏内存,当然,您可能会有其他泄漏,因此将为您提供可靠的基线。它也可能比您的方法更快,具有更方便的接口等
一般来说,您不应该重新发明控制盘,除非您有可用控制盘无法满足的特定需求,或者您实际上正在尝试学习如何创建控制盘或创建更好的控制盘。因此,您需要在内存中总共存储约9亿个值?即使每个值只有4个字节,可用的vir也会用完32位程序的实际地址空间。没有数据结构的更改可以解决这个问题。@T.C.但人们确实用Fortran运行这种模拟。没有任何选项可以处理这个问题吗?@aks:嗯-您可能会评论是否需要同时保留每个迭代的所有值,或者是否有某种方法处理和丢弃其中的一些值根据您的数据访问需求,您可能会考虑配置一个交换空间的好节点,或者明确地将这些值写入磁盘,直到它们需要AGIN。此外,您可以编译一个64位的应用程序吗?您有多少RAM?@ AKS,所以您确实只有900K值,并且只在每次迭代RAW中更新它们。r而不是制作新的?那么你可能需要在你的代码中寻找内存泄漏。正如T.C.所说,如果它通过了几次迭代然后崩溃,这表明它有足够的内存用于初始迭代,但后来泄漏了。更一般地说,std::unordered_map
听起来是正确的,除非你有连续的增量TIN键-那么你就可以有<代码>矢量< /代码>。如果Min和Max长度之间的变化很小,你可能想考虑<代码> STD::数组一个初始长度元素或尾随哨兵。对不起,但是大部分都是从我的头上跳下来的。让我重新表述我的问题。只知道我实际上在用C做什么。ode。我有898880个粒子,89888个单元格。每个单元格中有10个粒子。现在,由于我随机分配这些粒子的位置,我需要将每个粒子索引到它的单元格。因此,我使用链表将10个值映射到一个单元格。这些单元格由哈希表的哈希值标记。当我用200多次迭代模拟这个系统时,t程序以这样的方式终止:在抛出“std::bad_alloc”的实例后调用terminate那么,这些单元格、空间位置/体积是什么?为什么要使用哈希表呢?一个普通数组还不够吗?从我从代码中了解到,您的迭代是相互独立的?C
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);
}
-------
-------
}
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);
}
}