tbb:concurrent_hash_map <K,V>:英特尔线程构建模块(TBB)的示例代码

Contango

tbb::concurrent_hash_map<K,V>在英特尔线程构建模块(TBB)中寻找要使用的示例代码

我可以插入,但似乎无法读回值。

官员Intel的文档似乎有点欠缺的示例代码侧。

更新资料

最好的文档在Voss的“ Pro TBB:带有线程构建块的C ++并行编程”中。免费下载此书(属于公共领域)。

忽略英特尔文档。它们本质上是功能签名的集合。

Contango

英特尔TBB是开源的,在GitHub上

https://github.com/intel/tbb

要安装TBB,我用vcpkg是兼容LinuxWindowsMac是的,vcpkg来自Microsoft,但是它是100%跨平台的,开源的,并且非常流行。

Linux:

./vcpkg search tbb              # Find the package.
./vcpkg install tbb:x64-linux   # Install the package.

视窗:

vcpkg search tbb                # Find the package.
vcpkg install tbb:x64-windows   # Install the package.

编译:

  • 兼容所有现代的编译器,包括MSVC,GCC,LLVM,英特尔编译器(ICC)等,我用CMakegcc

也可以下载源代码并将标头和库提取到源代码树中,这同样有效。

码。

#include "tbb/concurrent_hash_map.h" // For concurrent hash map.

tbb::concurrent_hash_map<int, string> dict;
typedef tbb::concurrent_hash_map<int, string>::accessor dictAccessor; // See notes on accessor below.   

print("  - Insert key, method 1:\n");   
dict.insert({1,"k1"});
print("    - 1: k1\n");

print("  - Insert key, method 2:\n");
dict.emplace(2,"k2");
print("    - 2: k2\n");

string result;

{
    print("  - Read an existing key:\n");   
    dictAccessor accessor;
    const auto isFound = dict.find(accessor, 2);
    // The accessor functions as:
    // (a) a fine-grained per-key lock (released when it goes out of scope).
    // (b) a method to read the value.
    // (c) a method to insert or update the value.
    if (isFound == true) {
        print("    - {}: {}\n", accessor->first, accessor->second);
    }
}

{
    print("  - Atomically insert or update a key:\n");  
    dictAccessor accessor;
    const auto itemIsNew = dict.insert(accessor, 4);
    // The accessor functions as:
    // (a) a fine-grained per-key lock (released when it goes out of scope).
    // (b) a method to read the value.
    // (c) a method to insert or update the value.
    if (itemIsNew == true) {
        print("    - Insert.\n");
        accessor->second = "k4";
    }
    else {
        print("    - Update.\n");
        accessor->second = accessor->second + "+update";
    }
    print("    - {}: {}\n", accessor->first, accessor->second);     
}

{
    print("  - Atomically insert or update a key:\n");          
    dictAccessor accessor;
    const auto itemIsNew = dict.insert(accessor, 4);
    // The accessor functions as:
    // (a) a fine-grained per-key lock which is released when it goes out of scope.
    // (b) a method to read the value.
    // (c) a method to insert or update the value.
    if (itemIsNew == true) {
        print("    - Insert.\n");
        accessor->second = "k4";
    }
    else {
        print("    - Update.\n");
        accessor->second = accessor->second + "+update";
    }
    print("    - {}: {}\n", accessor->first, accessor->second);     
}

{
    print("  - Read the final state of the key:\n");            
    dictAccessor accessor;
    const auto isFound = dict.find(accessor, 4);
    print("    - {}: {}\n", accessor->first, accessor->second);
}

打印使用{fmtlib}进行打印;可以替换为cout <<

输出:

- Insert key, method 1:
  - 1: k1
- Insert key, method 2:
  - 2: k2
- Read an existing key:
  - 2: k2
- Atomically insert or update a key:
  - Insert.
  - 4: k4
- Atomically insert or update a key:
  - Update.
  - 4: k4+update
- Read the final state of the key:
  - 4: k4+update

其他哈希图

  • 参见:https : //tessil.github.io/2016/08/29/benchmark-hopscotch-map.html
  • 请参阅:std::unordered_map它具有更标准的API,并且在许多情况下是线程安全的,请参阅:unordered_map线程安全如果可能的话,建议使用它,因为它具有更简单的API。
  • 还有concurrent_unordered_map来自Intel TBB的。本质上是同一件事,一个键/值映射。但是,它年代久远,级别低得多,并且使用起来更困难。必须提供一个哈希器,一个相等运算符和一个分配器。即使在正式的英特尔文档中,也没有任何示例代码。尽管有数月的不时尝试,但我从未成功。它可能已过时,因为在上述免费书中没有提及(仅涵盖concurrent_hash_map)。不建议。

更新:读/写器锁

实际上有两个访问器,一个是读锁,一个是写锁:

  • const_accessor
  • accessor

如果使用find,则使用const_accessorread锁。如果使用inserterase,则使用accessor写锁(即它将等待所有读取完成,并阻止其他读取直到完成)。

这实际上等效于读取器/写入器锁,但仅在字典中使用单个字典键,而不是整个字典。

更新资料

学习曲线的最后一部分:对于键写,直到访问器超出范围,什么都不会发生。因此,可以使用CAS(比较和交换)来保留不超过几个机器指令的任何锁。

将其与数据库进行比较,访问器的范围就像一个事务。当访问器超出范围时,整个事务将提交给哈希映射。

更新资料

上面提到的免费书籍在的一章中有出色的性能提示concurrent_hash_map

结论

此哈希图的API功能强大,但有些尴尬。但是,它支持在插入/更新时进行细粒度的每键锁定。使用CAS时,只有少数机器指令才能持有任何锁这是其他任何语言都无法用任何语言提供的哈希图。std::unordered_map为了简单起见,建议从此开始只要两个线程不写入同一密钥,它就是线程安全的如果需要极快的性能,则可以选择重构或在上面使用[]访问器和编写兼容的包装insert_or_update()

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

Google本机客户端(NaCl,PNaCl)中的英特尔线程构建模块(TBB)

来自分类Dev

将std :: unique_ptr用作tbb :: concurrent_hash_map中的值时出现编译错误

来自分类Dev

用于Raspberry Pi 3的TBB英特尔线程构建基块

来自分类Dev

英特尔MIC上的英特尔TBB和Cilk Plus线程关联

来自分类Dev

英特尔 tbb 内存开销

来自分类Dev

英特尔TBB禁用嵌套并行性

来自分类Dev

英特尔TBB获得工作进展

来自分类Dev

英特尔tbb任务计划是否适合DBMS?

来自分类Dev

英特尔TBB禁用嵌套并行性

来自分类Dev

使用狙击模拟器使用英特尔 TBB 程序

来自分类Dev

英特尔TBB集成问题-Google测试项目中的VS2013编译错误

来自分类Dev

如何将tbb parallel_hash_map转换为常规std :: map?

来自分类Dev

为什么Map <K,V>不扩展Function <K,V>?

来自分类Dev

将 RDD[(K,V) 转换为 Map[K,List[V]]

来自分类Dev

了解英特尔内部指南中的代码示例

来自分类Dev

英特尔Edison模块

来自分类Dev

tbb :: concurrent_unordered_map :: unsafe_erase是否会使任何现有的迭代器无效?

来自分类Dev

什么是Map.Entry <K,V>接口?

来自分类Dev

从文件到Map <K,V>收集信息

来自分类Dev

从文件收集信息到Map <K,V>

来自分类Dev

Map.Entry是原始类型。泛型Map <K,V> .Entry <K,V>的引用应为

来自分类Dev

如何在Java中将List <Map <K,V >>转换为Map <K,List <V >>

来自分类Dev

英特尔服务器主板S1200V3RPS诊断LED显示未列出的开机自检代码

来自分类Dev

英特尔酷睿i7-4770K-健康的内核速度

来自分类Dev

英特尔高清显卡3000(i5-2540M)支持2K 27“

来自分类Dev

无法连接到Wifi(英特尔无线7265,华硕K501UW)

来自分类Dev

Haskell:对于Map中的每个(k,v),请对k和v执行IO()

来自分类Dev

线程构建块(TBB)使用lambda排队任务

来自分类Dev

premake5如何设置线程构建块(TBB)?

Related 相关文章

  1. 1

    Google本机客户端(NaCl,PNaCl)中的英特尔线程构建模块(TBB)

  2. 2

    将std :: unique_ptr用作tbb :: concurrent_hash_map中的值时出现编译错误

  3. 3

    用于Raspberry Pi 3的TBB英特尔线程构建基块

  4. 4

    英特尔MIC上的英特尔TBB和Cilk Plus线程关联

  5. 5

    英特尔 tbb 内存开销

  6. 6

    英特尔TBB禁用嵌套并行性

  7. 7

    英特尔TBB获得工作进展

  8. 8

    英特尔tbb任务计划是否适合DBMS?

  9. 9

    英特尔TBB禁用嵌套并行性

  10. 10

    使用狙击模拟器使用英特尔 TBB 程序

  11. 11

    英特尔TBB集成问题-Google测试项目中的VS2013编译错误

  12. 12

    如何将tbb parallel_hash_map转换为常规std :: map?

  13. 13

    为什么Map <K,V>不扩展Function <K,V>?

  14. 14

    将 RDD[(K,V) 转换为 Map[K,List[V]]

  15. 15

    了解英特尔内部指南中的代码示例

  16. 16

    英特尔Edison模块

  17. 17

    tbb :: concurrent_unordered_map :: unsafe_erase是否会使任何现有的迭代器无效?

  18. 18

    什么是Map.Entry <K,V>接口?

  19. 19

    从文件到Map <K,V>收集信息

  20. 20

    从文件收集信息到Map <K,V>

  21. 21

    Map.Entry是原始类型。泛型Map <K,V> .Entry <K,V>的引用应为

  22. 22

    如何在Java中将List <Map <K,V >>转换为Map <K,List <V >>

  23. 23

    英特尔服务器主板S1200V3RPS诊断LED显示未列出的开机自检代码

  24. 24

    英特尔酷睿i7-4770K-健康的内核速度

  25. 25

    英特尔高清显卡3000(i5-2540M)支持2K 27“

  26. 26

    无法连接到Wifi(英特尔无线7265,华硕K501UW)

  27. 27

    Haskell:对于Map中的每个(k,v),请对k和v执行IO()

  28. 28

    线程构建块(TBB)使用lambda排队任务

  29. 29

    premake5如何设置线程构建块(TBB)?

热门标签

归档