tbb并发hashmap实现字典ADT
tbb concurrent hashmap to implement dictionary ADT
我正在尝试使用 TBB 的并发哈希图实现字典 ADT。我在使用顺序版本时遇到问题。所以我猜我使用地图函数的方式有问题。
gdb
表示代码在对 erase(key)
的调用中挂起,后者又调用 lock
例程。闻起来像个僵局。这是 更正后的 代码:
#include<stdio.h>
#include "tbb/concurrent_hash_map.h"
using namespace tbb;
using namespace std;
typedef concurrent_hash_map<unsigned long,bool> tbbMap;
tbbMap map;
int findPercent;
int insertPercent;
int deletePercent;
unsigned long keyRange;
unsigned int lseed;
bool search(unsigned long key)
{
if(map.count(key))
{
return true;
}
else
{
return false;
}
}
bool insert(unsigned long key)
{
if(map.insert(std::make_pair(key,true)))
{
return true;
}
else
{
return(false);
}
}
bool remove(unsigned long key)
{
if(map.erase(key))
{
return true;
}
else
{
return(false);
}
}
void operateOnDictionary()
{
int chooseOperation;
unsigned long key;
int count=0;
while(count<10)
{
chooseOperation = rand_r(&lseed)%100;
key = rand_r(&lseed)%keyRange + 1;
if(chooseOperation < findPercent)
{
search(key);
}
else if (chooseOperation < insertPercent)
{
insert(key);
}
else
{
remove(key);
}
count++;
}
printf("done\n");
return;
}
int main()
{
findPercent = 10;
insertPercent= findPercent + 45;
deletePercent = insertPercent + 45;
keyRange = 5;
lseed = 0;
operateOnDictionary();
}
当然是访问器的错误使用。它应该是范围内的,RAII 对象,而不是全局对象。
实际发生的是 find()
或 insert()
获取访问器中的锁,但由于访问器未被破坏且未释放锁而未释放。然后,erase()
尝试获取相同的锁并挂起,因为它已经被获取了。
顺便说一句,如果您只需要检查密钥是否存在而不需要从中读取任何内容,请考虑使用 count()
。如果您不打算在插入后访问该元素,也不要使用 insert(with_accessor,key)
,请使用不使用访问器的 insert( std::make_pair(key, value) )
。
处理访问器意味着一定的运行时开销,因为它本质上是每个元素的锁。例如。比较没有访问器的 concurrent_unordered_map
和有访问器的 concurrent_hash_map
是不公平的。
我正在尝试使用 TBB 的并发哈希图实现字典 ADT。我在使用顺序版本时遇到问题。所以我猜我使用地图函数的方式有问题。
gdb
表示代码在对 erase(key)
的调用中挂起,后者又调用 lock
例程。闻起来像个僵局。这是 更正后的 代码:
#include<stdio.h>
#include "tbb/concurrent_hash_map.h"
using namespace tbb;
using namespace std;
typedef concurrent_hash_map<unsigned long,bool> tbbMap;
tbbMap map;
int findPercent;
int insertPercent;
int deletePercent;
unsigned long keyRange;
unsigned int lseed;
bool search(unsigned long key)
{
if(map.count(key))
{
return true;
}
else
{
return false;
}
}
bool insert(unsigned long key)
{
if(map.insert(std::make_pair(key,true)))
{
return true;
}
else
{
return(false);
}
}
bool remove(unsigned long key)
{
if(map.erase(key))
{
return true;
}
else
{
return(false);
}
}
void operateOnDictionary()
{
int chooseOperation;
unsigned long key;
int count=0;
while(count<10)
{
chooseOperation = rand_r(&lseed)%100;
key = rand_r(&lseed)%keyRange + 1;
if(chooseOperation < findPercent)
{
search(key);
}
else if (chooseOperation < insertPercent)
{
insert(key);
}
else
{
remove(key);
}
count++;
}
printf("done\n");
return;
}
int main()
{
findPercent = 10;
insertPercent= findPercent + 45;
deletePercent = insertPercent + 45;
keyRange = 5;
lseed = 0;
operateOnDictionary();
}
当然是访问器的错误使用。它应该是范围内的,RAII 对象,而不是全局对象。
实际发生的是 find()
或 insert()
获取访问器中的锁,但由于访问器未被破坏且未释放锁而未释放。然后,erase()
尝试获取相同的锁并挂起,因为它已经被获取了。
顺便说一句,如果您只需要检查密钥是否存在而不需要从中读取任何内容,请考虑使用 count()
。如果您不打算在插入后访问该元素,也不要使用 insert(with_accessor,key)
,请使用不使用访问器的 insert( std::make_pair(key, value) )
。
处理访问器意味着一定的运行时开销,因为它本质上是每个元素的锁。例如。比较没有访问器的 concurrent_unordered_map
和有访问器的 concurrent_hash_map
是不公平的。