如果有一個pthread_rwlock_t未持有寫鎖,有一個很大的開銷調用pthread_rwlock_rdlock/pthread_rwlock_unlock?開銷pthread_rwlock_rdlock的時候沒有寫鎖舉行
這是我想到的情況。如果還有其他啓發式可能有用,聽到它們會很高興。
你有一個簡單的程序,通過調用輸入的每一項功能轉換數據輸入到輸出結果的列表。一些輸入是相同的,或者至少是相似的,以至於你的函數可以記憶計算。假設你選擇使用散列來記憶這個函數。
隨着程序的進展,散列值增加,命中率接近100%。
下面是使用pthread_rwlock_t的可能解決方案。這樣做的一個缺點是,即使程序接近100%命中率,該函數仍在調用rdlock/unlock。
在某些時候,人們不禁要問,它是否是最好設置一個名爲「hash_frozen」在這一點把它當作常量共享數據標誌,而不是在這一點上添加任何按鍵。這似乎是一個笨重的解決方案。
struct hash h;
pthread_rwlock_t rwl = ...;
struct val fcn(struct inp i)
{
struct hashkey k;
struct hashval v;
pthread_rwlock_rdlock(rwl);
if ((k = hash_find(h, i)) != hash_end(h))
{
struct retval v = hash_val(k);
pthread_rwlock_unlock(rwl);
return v;
}
else
{
pthread_rwlock_unlock(rwl);
/* i'm aware that another thread could insert the value at
this moment, duplicating work, but let's ignore that minor
inefficiency. */
pthread_rwlock_wrlock(rwl);
struct retval v = compute_value(i);
k = hash_put(h, i);
hash_val(k) = v; /* let's say this is a macro, as in khash.h */
pthread_rwlock_unlock(rwl);
return v;
}
}
非常感謝@caf。目前我正在使用32個內核,並且實際上已經使用讀鎖實現了這一點。不幸的是,我的應用程序的確大部分時間都處於鎖定爭用狀態。我喜歡你的想法提前計算散列值,只鎖定散列的必要部分。不幸的是,我不認爲這種技術可以用於khash.h的散列,因爲它使用「二次探測」,這意味着一個單一的扁平數組(不是每個散列值下面的鏈表)。沒辦法隔絕桌子的一部分。 –