簡體   English   中英

C中的任何單用戶單生產者無鎖隊列實現?

[英]Any single-consumer single-producer lock free queue implementation in C?

我正在編寫一個帶有消費者線程和生產者線程的程序,現在看來隊列同步在程序中是一個很大的開銷,我找了一些無鎖隊列實現,但只發現了Lamport的版本和PPoPP的改進版本' 08:

enqueue_nonblock(data) {
    if (NULL != buffer[head]) {
        return EWOULDBLOCK;
    }
    buffer[head] = data;
    head = NEXT(head);
    return 0;
}

dequeue_nonblock(data) {
    data = buffer[tail];
    if (NULL == data) {
        return EWOULDBLOCK;
    }
    buffer[tail] = NULL;
    tail = NEXT(tail);
    return 0;
}

兩個版本都需要為數據預先分配的數組,我的問題是,是否存在使用malloc()動態分配空間的任何單用戶單生產者無鎖隊列實現?

另一個相關的問題是,如何測量隊列同步中的確切開銷? 比如pthread_mutex_lock()需要多長時間等。

如果你擔心性能,將malloc()添加到混合中將無濟於事。 如果您不擔心性能,為什么不簡單地通過互斥鎖控制對隊列的訪問。 您是否真的測量過這種實現的性能? 聽起來好像你正在走下熟悉的過早優化路線。

您展示的算法設法工作,因為雖然兩個線程共享資源(即隊列),但它們以非常特殊的方式共享它。 因為只有一個線程會改變隊列的頭索引(生產者),並且只有一個線程每個都改變尾索引(當然是消費者),所以你不能得到共享對象的不一致狀態。 生產者更新頭索引之前放入實際數據並且消費者更新尾索引之前讀取它想要的數據也很重要。

它的工作原理與b / c相同,陣列非常靜態; 兩個線程都可以依賴存儲元素。 您可能無法完全替換數組,但您可以做的是更改數組的用途。

即,不是將數據保存在數組中,而是使用它來保持指向數據的指針。 然后你可以使用malloc()和free()數據項,同時通過數組在線程之間傳遞引用(指針)。

此外,posix確實支持讀取納秒時鍾,但實際精度與系統有關。 你可以在之前和之后讀取這個高分辨率時鍾並且只是減去。

是。

存在許多無鎖多讀者多寫器隊列。

邁克爾和斯科特在1996年的論文中實施了一個。

我將(經過一些更多測試)發布一個包含此隊列的小型無鎖數據結構庫(在C中)。

你應該看看FastFlow庫

添加malloc會消除您可能獲得的任何性能提升,並且基於鎖定的結構也同樣有效。 這是因為malloc需要對堆進行某種CAS鎖定,因此某些形式的malloc有自己的鎖定,因此您可能會鎖定內存管理器。

要使用malloc,您需要預先分配所有節點並使用另一個隊列管理它們...

請注意,您可以制作某種形式的可擴展陣列,如果它已展開則需要鎖定。

此外,雖然互鎖在CPU上是無鎖定的,但它們會在指令期間放置內存鎖定和塊內存,並且通常會使管道停滯。

我記得幾年前看到一個看起來很有趣的東西,雖然我現在似乎無法找到它。 :(提出的無鎖實現確實需要使用CAS原語 ,盡管即使是鎖定實現(如果你不想使用CAS原語)也有相當好的性能特征---鎖只能防止多個讀者或者多個生產者同時進入隊列,生產者仍然沒有與消費者競爭。

我確實記得隊列背后的基本概念是創建一個鏈表,它總是有一個額外的“空”節點。 這個額外的節點意味着當列表為空時,列表的頭部和尾部指針只會引用相同的數據。 我希望我能找到這篇論文,我不是用我的解釋做算法正義...

啊,哈!

我發現有人在沒有文章的其余部分的情況下轉錄了算法 這可能是一個有用的起點。

我使用了一個相當簡單的隊列實現,符合大多數標准。 它使用了一個靜態最大大小的字節池,然后我們在其中實現了消息。 有一個進程可以移動的頭指針,以及另一個進程將移動的尾指針。

鎖仍然是必需的,但是我們使用了Peterson的2處理器算法 ,它非常輕巧,因為它不涉及系統調用。 只有非常小的,有界限的區域才需要鎖定:最多幾個CPU周期,所以你永遠不會阻塞很長時間。

我認為分配器可能是性能問題。 您可以嘗試使用自定義多線程內存分配器,它使用鏈接列表來維護釋放的塊。 如果您的塊不是(幾乎)相同的大小,您可以實現“伙伴系統內存分配器”,這是非常快的。 您必須將隊列(環形緩沖區)與互斥鎖同步。

為避免過多同步,您可以嘗試在每次訪問時向隊列中寫入/讀取多個值。

如果您仍想使用無鎖算法,則必須使用預先分配的數據或使用無鎖分配器。 有一篇關於無鎖分配器“可伸縮無鎖動態內存分配”和實現Streamflow的論文

在開始使用無鎖的東西之前,請看: 圓形無鎖緩沖區

這個實現使用C ++的new和delete,它可以使用malloc和free輕松移植到C標准庫:

http://www.drdobbs.com/parallel/writing-lock-free-code-a-corrected-queue/210604448?pgno=2

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM