【C/C++】ARM處理器對齊_偽共享問題

文章目錄

    • 1 什么是偽共享?
    • 2 為什么對齊?
    • 3 偽共享的實際影響
    • 4 為什么必須是 64 字節?
    • 5 其他替代方案
    • 6 驗證對齊效果
    • 總結

1 什么是偽共享?

偽共享是 多線程編程中的一種性能問題,其本質是:

  • 緩存行(Cache Line):現代 CPU 的緩存以固定大小的塊(緩存行)為單位管理數據,常見緩存行大小為 64 字節(如 x86/x64 CPU)。
  • 共享緩存行:如果兩個獨立的變量(如 _bottom_top)位于同一個緩存行中,即使它們被不同線程訪問(如一個線程寫 _bottom,另一個線程讀 _top),也會導致緩存行被頻繁標記為“無效”(Cache Invalidation)。
  • 性能損失:頻繁的緩存同步(從 L1/L2 緩存到主存)會顯著降低程序性能。

避免偽共享(False Sharing),從而提升多線程程序的性能


2 為什么對齊?

以64字節對齊為例:
通過 alignas(64) 強制變量對齊到 64 字節邊界,可以確保:

  • 獨占緩存行:每個變量(如 _bottom_top)獨占一個完整的緩存行(64 字節),避免與其他變量共享。
  • 隔離修改:當一個線程修改 _bottom 時,不會觸發其他線程中 _top 所在緩存行的無效化,反之亦然。

示例內存布局:

// 未對齊時(偽共享)
Cache Line 0: | _bottom (8 bytes) | _top (8 bytes) | ...(剩余 48 字節)|// 對齊到 64 字節后(避免偽共享)
Cache Line 0: | _bottom (8 bytes) | padding (56 bytes)            |
Cache Line 1: | _top (8 bytes)    | padding (56 bytes)            |

32 位 ARM 系統中,為了避免偽共享(False Sharing),通常建議的對齊大小為 32 字節64 字節,具體取決于目標處理器的緩存行(Cache Line)大小。

  1. ARM 系統的緩存行大小
    32 位 ARM 處理器的緩存行大小因架構和型號而異:
  • 較舊 ARMv6/ARMv7 處理器(如 Cortex-A8/A9)通常使用 32 字節 的緩存行。
  • 較新 ARMv7/ARMv8 處理器(如 Cortex-A53/A72)可能采用 64 字節 的緩存行(與 x86/x64 對齊)。

具體需查閱目標 CPU 的文檔(如 Technical Reference Manual)確認。

  1. 對齊建議
  • 通用保守方案:32 字節對齊
    若不確定目標處理器的緩存行大小,可保守對齊到 32 字節(覆蓋舊型號的 32 字節緩存行):
alignas(32) std::atomic<size_t> _bottom;
alignas(32) std::atomic<size_t> _top;
  • 針對新型號:64 字節對齊
    若目標處理器為較新的 ARMv8 或已知緩存行為 64 字節(如部分 Cortex-A 系列),可直接對齊到 64 字節
alignas(64) std::atomic<size_t> _bottom;
alignas(64) std::atomic<size_t> _top;
  • C++17 自適應方案
    若支持 C++17,使用 std::hardware_destructive_interference_size 自動適配緩存行大小:
#include <new>
alignas(std::hardware_destructive_interference_size) std::atomic<size_t> _bottom;
alignas(std::hardware_destructive_interference_size) std::atomic<size_t> _top;

  1. 驗證對齊效果
    通過代碼檢查變量地址是否為對齊值的整數倍:
#include <iostream>
#include <cstdint>int main() {alignas(32) std::atomic<size_t> _bottom;alignas(32) std::atomic<size_t> _top;// 檢查對齊是否成功auto check_alignment = [](const auto& var, size_t alignment) {uintptr_t addr = reinterpret_cast<uintptr_t>(&var);return (addr % alignment == 0) ? "Success" : "Failed";};std::cout << "_bottom 對齊 32: " << check_alignment(_bottom, 32) << "\n";std::cout << "_top 對齊 32: " << check_alignment(_top, 32) << "\n";return 0;
}
  1. 實際性能對比
場景32 字節緩存行(對齊 32)64 字節緩存行(對齊 64)未對齊(偽共享)
線程競爭開銷低(若緩存行為 64)高(頻繁緩存失效)
內存占用略高(填充空間)更高(填充空間)

  1. 適用場景總結
  • 嵌入式/IoT 設備(舊款 ARMv6/v7):優先對齊 32 字節
  • 高性能 ARM 處理器(如 Cortex-A72):對齊 64 字節
  • 跨平臺代碼:使用 C++17 的 std::hardware_destructive_interference_size

32 位 ARM 系統中,若無明確緩存行信息,默認對齊到 32 字節是安全選擇。
若針對新型處理器或已知緩存行為 64 字節,則對齊到 64 字節。通過合理對齊,可顯著減少偽共享帶來的性能損失。

3 偽共享的實際影響

假設 _bottom_top 是一個無鎖隊列的頭尾指針:

  • 線程 A 頻繁修改 _bottom(入隊操作)。
  • 線程 B 頻繁修改 _top(出隊操作)。
  • 如果它們共享同一個緩存行,每次修改都會導致對方線程的緩存失效,性能可能下降 數倍甚至數十倍

通過對齊到 64 字節,兩者的修改完全隔離,避免不必要的緩存同步。


4 為什么必須是 64 字節?

  • 緩存行大小:x86/x64 CPU 的緩存行大小通常為 64 字節,ARM 架構也普遍采用 64 字節。對齊到緩存行大小是最直接的方法。
  • 兼容性:即使某些 CPU 的緩存行更小(如 32 字節),對齊到 64 字節也能覆蓋所有常見情況。

5 其他替代方案

  1. 填充字節(Padding)
    手動在變量間插入填充數據,強制隔離:
struct AlignedData {std::atomic<size_t> _bottom;char padding[64 - sizeof(std::atomic<size_t>)];std::atomic<size_t> _top;
};
  • 缺點:需手動計算填充大小,不夠靈活。
  1. C++17 std::hardware_destructive_interference_size
    C++17 提供了表示緩存行大小的常量:
#include <new>
alignas(std::hardware_destructive_interference_size) std::atomic<size_t> _bottom;
alignas(std::hardware_destructive_interference_size) std::atomic<size_t> _top;
  • 優點:代碼可移植,自動適配不同平臺的緩存行大小。
  • 缺點:需要 C++17 支持。

6 驗證對齊效果

可以通過以下方式驗證變量是否對齊到 64 字節:

#include <iostream>
#include <cstdint>int main() {alignas(64) std::atomic<size_t> _bottom;alignas(64) std::atomic<size_t> _top;// 檢查地址是否為 64 的倍數std::cout << "Address of _bottom: " << &_bottom << " (aligned: "<< ((reinterpret_cast<uintptr_t>(&_bottom) % 64 == 0) << ")\n";std::cout << "Address of _top: " << &_top << " (aligned: "<< ((reinterpret_cast<uintptr_t>(&_top) % 64 == 0) << ")\n";return 0;
}

總結

  • 對齊到 64 字節:通過獨占緩存行,避免 _bottom_top 之間的偽共享。
  • 適用場景:高頻并發訪問的原子變量(如無鎖數據結構、計數器等)。
  • 推薦方法:優先使用 alignas(64) 或 C++17 的 std::hardware_destructive_interference_size

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/80442.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/80442.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/80442.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Kafka Controller的作用是什么?故障時如何恢復? (管理分區和副本狀態;通過ZooKeeper選舉新Controller)

Apache Kafka Controller 是 Kafka 集群的核心協調組件&#xff0c;主要承擔兩大核心職責&#xff1a; 一、核心作用 分區領導者選舉 1 // 分區領導者選舉邏輯示例&#xff08;偽代碼&#xff09; def electLeader(partition: Partition): Unit {val isr partition.inSync…

阿里云前端Nginx部署完,用ip地址訪問卻總訪問不到,為什么?檢查安全組是否設置u為Http(80)!

根據你的描述&#xff0c;Ping測試顯示數據包無丟失但無法通過公網IP訪問服務&#xff0c;說明網絡基礎層&#xff08;ICMP協議&#xff09;是通暢的&#xff0c;但更高層&#xff08;如TCP/UDP協議或服務配置&#xff09;存在問題。以下是系統性排查與解決方案&#xff1a; 一…

關于STM32 SPI收發數據異常

問題描述&#xff1a; STM32主板做SPI從機&#xff0c;另一塊linux主板做主機&#xff0c;通信的時候發現從機可以正確接收到主機數據&#xff0c;但是主機接收從機數據時一直不對&#xff0c;是隨機值。 問題原因&#xff1a; 剛發現問題的時候&#xff0c;用邏輯分析儀抓包…

特勵達力科LeCroy推出Xena Freya Z800 800GE高性能的800G以太網測試平臺

Xena Freya Z800 800GE 是由全球領先的測試與測量解決方案提供商特勵達力科公司&#xff08;Teledyne LeCroy&#xff09;開發的高性能以太網測試平臺&#xff0c;專為滿足從10GE到800GE數據中心互連速度的需求而設計。特勵達力科公司在網絡測試領域擁有超過50年的技術積累&…

基于Django框架的股票分紅數據爬蟲和展示系統

項目截圖 一、項目簡介 本項目是一個基于 Django 框架的股票分紅數據爬蟲和展示系統。它可以從東方財富網站爬取股票分紅數據&#xff0c;并將數據存儲到 Django 數據庫中&#xff0c;同時提供數據查詢、導出和圖表展示功能。該系統為用戶提供了一個方便的平臺&#xff0c;用于…

nginx性能優化與深度監控

一、性能調優方向 1. 系統層面優化 內核參數調整 TCP隊列與連接管理&#xff1a; net.core.somaxconn&#xff08;最大連接隊列長度&#xff0c;建議設為65535&#xff09;net.ipv4.tcp_max_syn_backlog&#xff08;SYN隊列長度&#xff0c;建議65535&#xff09;net.ipv4.tc…

深入解析 Vision Transformer (ViT) 與其在計算機視覺中的應用

在近年來&#xff0c;深度學習尤其在計算機視覺領域取得了巨大的進展&#xff0c;而 Vision Transformer&#xff08;ViT&#xff09;作為一種新的視覺模型&#xff0c;它的表現甚至在許多任務中超過了傳統的卷積神經網絡&#xff08;CNN&#xff09;&#xff0c;如 ResNet。在…

PXE_Kickstart_無人值守自動化安裝系統

文章目錄 1. PXE2. 配置服務參數2.1 tftp服務配置2.2 dhcp服務配置2.3 http服務配置 3. 配置PXE環境3.1 網絡引導文件pxelinux.03.2 掛載鏡像文件3.3 創建配置文件default3.4 復制鏡像文件和驅動文件3.5 修改default文件3.6 配置ks.cfg文件 4. PXE客戶端4.1 創建虛擬機&#xf…

鴻蒙NEXT開發動畫案例4

1.創建空白項目 2.Page文件夾下面新建Spin.ets文件&#xff0c;代碼如下&#xff1a; /*** TODO SpinKit動畫組件 - 雙粒子旋轉縮放動畫* author: CSDN-鴻蒙布道師* since: 2025/05/08*/ ComponentV2 export struct SpinFour {// 參數定義Require Param spinSize: number 36…

基于STM32、HAL庫的CP2102-GMR USB轉UART收發器 驅動程序設計

一、簡介: CP2102-GMR是Silicon Labs公司生產的一款USB轉UART橋接芯片,主要特點包括: 集成USB 2.0全速功能控制器 內置USB收發器,無需外部電阻 工作電壓:3.0V至3.6V 支持的數據格式:數據位8,停止位1,無校驗 最高支持1Mbps的波特率 內置512字節接收緩沖區和512字節發送…

Ubuntu 22虛擬機【網絡故障】快速解決指南

Ubuntu22虛擬機突然無法連接網絡了&#xff0c;以下是故障排除步驟記錄。 Ubuntu 22虛擬機網絡故障快速解決指南 當在虛擬機中安裝的 Ubuntu 22 系統出現 ping: connect: 網絡不可達 和 ping: www.baidu.com: 域名解析出現暫時性錯誤的報錯時&#xff0c;通常意味著虛擬機無法…

實戰springcloud alibaba

實戰springcloud alibaba 前言 如何搭建一套最新的springcloud alibaba&#xff0c;以適配項目升級需求&#xff1f; 1.版本的選擇 2.各組件的適配 3.新技術的敏感性 4.前瞻性&#xff0c;幾年內不會被淘汰 參考資料&#xff1a;Spring Cloud Alibaba 參考文檔 https://spring…

泰迪杯特等獎案例學習資料:基于卷積神經網絡與集成學習的網絡問政平臺留言文本挖掘與分析

(第八屆“泰迪杯”數據挖掘挑戰賽A題特等獎案例深度解析) 一、案例背景與核心挑戰 1.1 應用場景與行業痛點 隨著“互聯網+政務”的推進,網絡問政平臺成為政府與民眾溝通的重要渠道。某市問政平臺日均接收留言超5000條,涉及民生、環保、交通等20余類訴求。然而,傳統人工…

DVWA靶場保姆級通關教程--06不安全驗證機制

提示&#xff1a;文章寫完后&#xff0c;目錄可以自動生成&#xff0c;如何生成可參考右邊的幫助文檔 文章目錄 目錄 文章目錄 前言 原理詳解 1. 前后端驗證邏輯不一致 2. 驗證碼值保存在客戶端 3. 驗證碼可預測或重復 4. 驗證碼驗證與邏輯解耦 一、處理關卡報錯 二、low級別源…

【LeetCode Hot100 | 每日刷題】排序數組

912. 排序數組 - 力扣&#xff08;LeetCode&#xff09; 題目&#xff1a; 給你一個整數數組 nums&#xff0c;請你將該數組升序排列。 你必須在 不使用任何內置函數 的情況下解決問題&#xff0c;時間復雜度為 O(nlog(n))&#xff0c;并且空間復雜度盡可能小。 示例 1&…

Windows系統下使用Kafka和Zookeeper,Python運行kafka(二)

1.配置 Zookeeper 進入解壓后的 Zookeeper 目錄&#xff08;例如 F:\zookeeper\conf&#xff09;&#xff0c;復制 zoo_sample.cfg 文件并命名為 zoo.cfg&#xff08;如果 zoo.cfg 已經存在&#xff0c;則直接編輯該文件&#xff09;。 打開 zoo.cfg 文件&#xff0c;配置相關…

Web 自動化之 HTML JavaScript 詳解

文章目錄 一、HTML 常用標簽二、javascript 腳本1、什么是 javascript(js)2、 js變量和函數3、js 彈窗處理4、js 流程控制語句和 switch 結構語句應用 一、HTML 常用標簽 HTML&#xff1a;超文本標記語言 超文本&#xff1a;不僅只包含文字&#xff0c;還有超鏈接、視頻…這些…

el-date-picker的type為daterange時僅對開始日期做限制

文章目錄 前言繡球html代碼一、正確代碼二、錯誤代碼 前言繡球 需求是這樣的&#xff0c;開始日期需要限制只能選擇今天的日期&#xff0c;結束日期只能選擇今天之后的日期。結束日期很常見&#xff0c;但是單純限制開始日期&#xff0c;還是蠻少見的&#xff0c;尤其是datera…

觀測云:安全、可信賴的監控觀測云服務

引言 近日&#xff0c;“TikTok 遭歐盟隱私監管機構調查并處以 5.3 億歐元”一案&#xff0c;再次引發行業內對數據合規等話題的熱議。據了解&#xff0c;僅 2023 年一年就產生了超過 20 億美元的 GDPR 罰單。這凸顯了在全球化背景下&#xff0c;企業在數據隱私保護方面所面臨…

認識中間件-以及兩個簡單的示例

認識中間件-以及兩個簡單的示例 什么是中間件一個響應處理中間件老朋友 nest g如何使用為某個module引入全局引入編寫邏輯一個日志中間件nest g mi 生成引入思考代碼進度什么是中間件 官方文檔 中間件是在路由處理程序之前調用的函數。中間件函數可以訪問請求和響應對象,以及…