OverviewFilesCommitsIssuesDocsReleasesPeers

opencog-SimpleGPUHashTable commits / ea8f59a

Use kEmpty=0xffffffff as empty node
ea8f59a473c7cec75d2effdbef0c9c9b2ac9cce3
by David Farrell <nosferalatu@gmail.com> · 2020-03-02T01:11:09.000Z

Changed files (3) +23 -19

src/linearprobing.cu +18 -16
……@@ -14,6 +14,20 @@ __device__ uint32_t hash(uint32_t k)
1414 return k & (kHashTableCapacity-1);
1515}
1616
17// Create a hash table. For linear probing, this is just an array
18// of KeyValues. The hash table is
19KeyValue* create_hashtable(uint32_t capacity) {
20 // Allocate memory
21 KeyValue* hashtable;
22 cudaMalloc(&hashtable, sizeof(KeyValue) * kHashTableCapacity);
23
24 // Initialize hash table to empty
25 static_assert(kEmpty == 0xffffffff, "memset expected kEmpty=0xffffffff");
26 cudaMemset(hashtable, 0xff, sizeof(KeyValue) * kHashTableCapacity);
27
28 return hashtable;
29}
30
1731__global__ void gpu_hashtable_insert(KeyValue* hashtable, const KeyValue* kvs, unsigned int numkvs)
1832{
1933 unsigned int threadid = blockIdx.x*blockDim.x + threadIdx.x;
……@@ -25,8 +39,8 @@ __global__ void gpu_hashtable_insert(KeyValue* hashtable, const KeyValue* kvs, u
2539
2640 while (true)
2741 {
28 uint32_t prev = atomicCAS(&hashtable[slot].key, 0, key);
29 if (prev == 0 || prev == key)
42 uint32_t prev = atomicCAS(&hashtable[slot].key, kEmpty, key);
43 if (prev == kEmpty || prev == key)
3044 {
3145 hashtable[slot].value = value;
3246 break;
……@@ -37,18 +51,6 @@ __global__ void gpu_hashtable_insert(KeyValue* hashtable, const KeyValue* kvs, u
3751 }
3852}
3953
40KeyValue* create_hashtable(uint32_t capacity)
41{
42 // Allocate memory
43 KeyValue* hashtable;
44 cudaMalloc(&hashtable, sizeof(KeyValue)*kHashTableCapacity);
45
46 // Initialize hash table to empty
47 cudaMemset(hashtable, 0, sizeof(KeyValue)*kHashTableCapacity);
48
49 return hashtable;
50}
51
5254void insert_hashtable(KeyValue* pHashTable, const KeyValue* kvs, uint32_t num_kvs)
5355{
5456 // Copy the keyvalues to the GPU
……@@ -68,7 +70,7 @@ void insert_hashtable(KeyValue* pHashTable, const KeyValue* kvs, uint32_t num_kv
6870
6971 cudaEventRecord(start);
7072
71 // Hash table insertion
73 // Insert all the keys into the hash table
7274 int gridsize = ((uint32_t)num_kvs + threadblocksize - 1) / threadblocksize;
7375 gpu_hashtable_insert<<<gridsize, threadblocksize>>>(pHashTable, device_kvs, (uint32_t)num_kvs);
7476
……@@ -96,7 +98,7 @@ std::vector<KeyValue> iterate_hashtable(KeyValue* pHashTable)
9698
9799 for (uint32_t i = 0; i < kHashTableCapacity; i++)
98100 {
99 if (pHostHashTable[i].key != 0)
101 if (pHostHashTable[i].key != kEmpty)
100102 {
101103 kvs.push_back(pHostHashTable[i]);
102104 }
src/linearprobing.h +2 -2
……@@ -1,7 +1,5 @@
11#pragma once
22
3#define ASSERT(X) if (!(X)) __debugbreak();
4
53struct KeyValue
64{
75 uint32_t key;
……@@ -12,6 +10,8 @@ const uint32_t kHashTableCapacity = 128 * 1024 * 1024;
1210
1311const uint32_t kNumKeyValues = kHashTableCapacity / 2;
1412
13const uint32_t kEmpty = 0xffffffff;
14
1515KeyValue* create_hashtable(uint32_t initialCapacity);
1616
1717void insert_hashtable(KeyValue* hashtable, const KeyValue* kvs, uint32_t num_kvs);
src/main.cpp +3 -1
……@@ -8,11 +8,13 @@
88#include "random"
99#include "linearprobing.h"
1010
11// Create random keys/values in the range [0, kEmpty)
12// kEmpty is used to indicate an empty slot
1113std::vector<KeyValue> generate_random_keyvalues()
1214{
1315 std::random_device rd;
1416 std::mt19937 gen(rd()); // mersenne_twister_engine
15 std::uniform_int_distribution<uint32_t> dis(1, 0xffffffff); // 0 is reserved for empty keys
17 std::uniform_int_distribution<uint32_t> dis(0, kEmpty-1);
1618
1719 std::vector<KeyValue> kvs;
1820 kvs.reserve(kNumKeyValues);