切換語言為:簡體

多執行緒程式設計中的偽共享是什麼?

  • 爱糖宝
  • 2024-10-20
  • 2045
  • 0
  • 0

偽共享(False Sharing)是多執行緒程式設計中的一種效能問題,它發生在多個執行緒同時訪問不同的變數,但這些變數卻共享同一快取行(cache line)時。儘管這些變數並不相互依賴,但由於它們的儲存位置在快取中靠得很近,導致處理器頻繁地無效化(invalidate)快取行,從而影響效能。

快取行的基本概念

在現代計算機中,CPU 使用快取來提高記憶體訪問速度。快取通常分為多個層次(L1、L2、L3),每個層次的容量和訪問速度各不相同。CPU 從主記憶體讀取資料時,通常是以快取行(通常是 64 位元組)為單位進行讀取的。這意味著,訪問快取行中的一個位元組將導致整個快取行被載入到 CPU 的快取中。

偽共享的發生

偽共享通常發生在以下情況下:

  1. 多個執行緒:多個執行緒併發地訪問和修改不同的變數。

  2. 相同的快取行:這些變數位於同一個快取行內,導致 CPU 每次更新某個變數時都要使得包含其他變數的快取行失效。

例如,考慮以下程式碼:

#include <iostream>
#include <thread>
#include <vector>
#include <chrono>

const int NUM_THREADS = 4;
const int NUM_ITERATIONS = 10000000;

struct Data {
    int a; // 變數 a
    int b; // 變數 b
    // 可能存在偽共享
};

Data data[NUM_THREADS];

void increment(int index) {
    for (int i = 0; i < NUM_ITERATIONS; ++i) {
        data[index].a++; // 執行緒修改 a
        data[index].b++; // 執行緒修改 b
    }
}

int main() {
    std::vector<std::thread> threads;
    for (int i = 0; i < NUM_THREADS; ++i) {
        threads.emplace_back(increment, i);
    }

    for (auto& t : threads) {
        t.join();
    }

    return 0;
}

在這個示例中,data 陣列的每個元素都有兩個整數變數 ab。假設這兩個變數儲存在同一個快取行中,當多個執行緒同時修改 ab 時,可能會導致偽共享。這是因為每個執行緒在更新 a 時,可能會導致儲存 b 的快取行失效,從而引發頻繁的快取行無效化。

偽共享的影響

偽共享會導致以下幾個問題:

  1. 效能下降:由於頻繁的快取行無效化,CPU 可能會花費大量時間在資料一致性上,從而影響整體效能。

  2. 增加的延遲:每次訪問共享快取行時,CPU 需要等待,從而增加了延遲。

  3. 吞吐量降低:在多執行緒環境中,偽共享可能導致 CPU 的利用率下降,影響吞吐量。

如何避免偽共享

避免偽共享的方法主要包括:

  1. 記憶體對齊:透過確保變數在記憶體中對齊到快取行邊界,可以減少偽共享的發生。例如,使用 alignas 關鍵字來對齊結構體。

    struct alignas(64) Data {
        int a;
        int b;
    };

  2. 增加快取行的使用:將變數放置在不同的快取行中,可以有效避免偽共享。例如,在結構體中新增填充變數(padding)以確保不同變數位於不同的快取行。

    struct Data {
        int a;
        char padding[60]; // 填充到 64 位元組
        int b;
    };

  3. 分離數據結構:在多執行緒應用中,將資料分散到不同的結構體中,每個執行緒使用獨立的結構體,避免共享資料。

  4. 使用原子操作:在某些情況下,可以使用原子操作(如 std::atomic)來減少對共享變數的直接訪問,降低偽共享的風險。

總結

偽共享是多執行緒程式設計中的一個常見效能問題,它發生在多個執行緒同時訪問位於同一快取行中的不同變數時。透過合理的記憶體對齊和數據結構設計,可以有效避免偽共享,提升多執行緒應用的效能。在進行高效能多執行緒開發時,瞭解偽共享及其影響至關重要。

0則評論

您的電子郵件等資訊不會被公開,以下所有項目均必填

OK! You can skip this field.