CUDA 中Thrust exclusive_scan使用詳解

1. 基本概念

  • Thrust 是 NVIDIA CUDA 提供的類似 C++ STL 的并行算法庫。

  • Scan (前綴和):給定數組 [a0, a1, a2, ...],產生前綴和序列。

  • Exclusive Scan (排他前綴和)

    • 輸出位置 i 存放的是輸入數組中 0 到 i-1 的累積結果
    • 換句話說,結果向右錯位一格,首位放初始值

公式:

output[0] = init
output[i] = input[0] ⊕ input[1] ⊕ ... ⊕ input[i-1],  (i > 0)

其中 是二元操作符(默認是加法)。

inclusive_scan 的區別:

  • inclusive:包含當前位置 → output[i] = input[0] + ... + input[i]
  • exclusive:不包含當前位置 → output[i] = input[0] + ... + input[i-1]

2. 函數原型

// 版本 1:默認加法
template <typename InputIterator, typename OutputIterator>
OutputIterator exclusive_scan(InputIterator first, InputIterator last, OutputIterator result);// 版本 2:指定初始值
template <typename InputIterator, typename OutputIterator, typename T>
OutputIterator exclusive_scan(InputIterator first, InputIterator last, OutputIterator result, T init);// 版本 3:指定二元運算符
template <typename InputIterator, typename OutputIterator, typename T, typename BinaryFunction>
OutputIterator exclusive_scan(InputIterator first, InputIterator last, OutputIterator result, T init, BinaryFunction binary_op);

參數說明:

  • first, last:輸入區間
  • result:輸出區間
  • init:初始值(默認 0)
  • binary_op:二元操作(默認 thrust::plus<T>()

返回值:輸出迭代器(即 result + (last - first)


3. 示例代碼

🔹 默認加法 + 默認初始值

#include <thrust/scan.h>
#include <thrust/device_vector.h>
#include <iostream>int main() {thrust::device_vector<int> d_in{1, 2, 3, 4};thrust::device_vector<int> d_out(4);thrust::exclusive_scan(d_in.begin(), d_in.end(), d_out.begin());// 輸出:0 1 3 6for (int x : d_out) std::cout << x << " ";
}

解釋:

  • 輸入 [1, 2, 3, 4]
  • 輸出 [0, 1, 3, 6]

指定初始值

thrust::exclusive_scan(d_in.begin(), d_in.end(), d_out.begin(), 10);

輸入 [1, 2, 3, 4],結果 [10, 11, 13, 16]


自定義運算符(乘法)

struct multiply
{__host__ __device__ int operator()(const int &a, const int &b) const {return a * b;}
};thrust::exclusive_scan(d_in.begin(), d_in.end(), d_out.begin(), 1, multiply());

輸入 [1, 2, 3, 4],結果 [1, 1, 2, 6]


4. 內部實現原理

  • exclusive_scan 在 GPU 上通常使用 并行前綴和算法(Blelloch Scan):

    1. 上行階段(reduce):樹形歸約,計算部分和。
    2. 下行階段(down-sweep):回傳累積和,得到 exclusive 結果。
  • 復雜度:O(n)

  • 并行化效率:在 CUDA 中可利用 warp shuffle / shared memory 優化。


5. 常見應用

  1. 數組索引計算:比如稀疏矩陣非零元素位置。
  2. 并行 compact/filter:布爾標記數組 → 前綴和 → 計算輸出位置。
  3. 動態內存分配:統計每個線程寫入位置。
  4. 圖算法:CSR 格式構建、鄰接表索引。

6. 易錯點

exclusive vs inclusive:結果差一個位置,常見 bug。
初始值:沒設置時默認 0,很多人誤以為會報錯。
in-place 使用:輸入和輸出可以是同一個 vector(安全)。
自定義運算符:必須滿足結合律(associative),否則結果不穩定。


7. 性能優化

  • exclusive_scan 已由 Thrust 內部優化,適合中大規模數組。
  • 小規模數組時,CPU std::exclusive_scan 可能更快。
  • 多次調用時建議 預分配 device_vector,避免反復分配內存。

8、 exclusive_scan vs inclusive_scan 對比表

特性exclusive_scaninclusive_scan
定義輸出位置 i 是輸入 [0..i-1] 的累積和,當前位置 不包含輸出位置 i 是輸入 [0..i] 的累積和,當前位置 包含
首元素結果 output[0] = init(默認 0)結果 output[0] = input[0]
數學表達式out[i] = init ⊕ in[0] ⊕ ... ⊕ in[i-1]out[i] = in[0] ⊕ in[1] ⊕ ... ⊕ in[i]
輸入 [1, 2, 3, 4],init=0輸出 [0, 1, 3, 6]輸出 [1, 3, 6, 10]
典型用途計算 索引偏移、數組 compaction、CSR 圖結構直接得到前綴累計量,例如直方圖累計、累積分布函數 (CDF)

9、典型應用場景代碼

1?、數組索引偏移(exclusive_scan)

常見于 稀疏矩陣 / 圖的 CSR 格式構建

#include <thrust/scan.h>
#include <thrust/device_vector.h>
#include <iostream>int main() {thrust::device_vector<int> flags{1, 0, 1, 1, 0};thrust::device_vector<int> indices(flags.size());// exclusive_scan:計算每個位置在輸出數組的起始索引thrust::exclusive_scan(flags.begin(), flags.end(), indices.begin());// 輸出: 0 1 1 2 3for (int x : indices) std::cout << x << " ";
}

解釋:

  • flags 表示某位置是否有效
  • exclusive_scan 得到每個有效元素在輸出數組中的索引位置

2?、數組 compaction(exclusive_scan + scatter)

保留布爾條件為真的元素,常用于 過濾數據

#include <thrust/scan.h>
#include <thrust/copy.h>
#include <thrust/device_vector.h>
#include <iostream>int main() {thrust::device_vector<int> data{3, 7, 0, 4, 9};thrust::device_vector<int> flags{1, 0, 1, 0, 1};thrust::device_vector<int> indices(flags.size());thrust::device_vector<int> result(3); // 預估有效數量thrust::exclusive_scan(flags.begin(), flags.end(), indices.begin());// 根據 flags 把有效元素寫入結果數組for (int i = 0; i < flags.size(); i++) {if (flags[i]) result[indices[i]] = data[i];}// 輸出: 3 0 9for (int x : result) std::cout << x << " ";
}

3?、累積分布函數 CDF(inclusive_scan)

常用于 直方圖后處理

#include <thrust/scan.h>
#include <thrust/device_vector.h>
#include <iostream>int main() {thrust::device_vector<int> hist{2, 3, 5, 4};thrust::device_vector<int> cdf(hist.size());thrust::inclusive_scan(hist.begin(), hist.end(), cdf.begin());// 輸出: 2 5 10 14for (int x : cdf) std::cout << x << " ";
}

解釋:

  • 輸入直方圖 [2,3,5,4]
  • inclusive_scan 得到累積分布 [2,5,10,14]

4?、并行前綴乘積(inclusive_scan with multiply)

用于 概率鏈式計算

struct multiply {__host__ __device__ float operator()(float a, float b) const {return a * b;}
};thrust::device_vector<float> probs{0.9, 0.8, 0.7, 0.6};
thrust::device_vector<float> cumprod(probs.size());thrust::inclusive_scan(probs.begin(), probs.end(), cumprod.begin(), multiply());// 輸入: 0.9 0.8 0.7 0.6
// 輸出: 0.9 0.72 0.504 0.3024

10、 總結

  • exclusive_scan:計算“排他前綴和”,結果右移一位,首位為初始值。
  • 三種重載:默認 / 指定 init / 指定 init + 運算符。
  • 應用廣泛:稀疏矩陣、圖算法、并行 compaction。
  • 注意事項:exclusive vs inclusive,init 值,自定義運算符必須結合律。

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

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

相關文章

Linux -- 信號【上】

目錄 一、信號的引入 1、信號概念 2、signal函數 普通標準信號詳解表 3、前臺/后臺進程 3.1 概念 3.2 查看后臺進程 3.3 后臺進程拉回前臺 3.4 終止后臺進程 3.5 暫停前臺進程 3.6 回復運行后臺進程 4、發信號的本質 二、信號的產生 1、終端按鍵 2、系統調用 2…

Altium Designer(AD)自定義PCB外觀顏色

目錄 1視圖設置界面介紹 2PCB阻焊層顏色設置 2.1進入視圖設置界面 2.2阻焊層顏色設置 2.3頂層和底層阻焊層顏色設置 2.4頂層阻焊層試圖效果 2.5底層阻焊層試圖效果 3設置PCB絲印顏色設置 3.1找到絲印設置選項 3.2設置頂層和底層絲印顏色 3.3頂層絲印 3.4底層絲印 4…

5天改造,節能50%!冷能改造如何實現“不停產節能”?

你有沒有發現一個現象&#xff1f;很多工廠老板一提到節能改造&#xff0c;第一反應就是搖頭。不是不想省電費&#xff0c;而是怕停產。停產一天損失幾十萬&#xff0c;改造周期動輒幾個月&#xff0c;這賬怎么算都不劃算。但如果我告訴你&#xff0c;有一種改造方式&#xff0…

【Flink】窗口

目錄窗口窗口的概念窗口的分類滾動窗口&#xff08;Tumbling Windows&#xff09;滑動窗口&#xff08;Sliding Windows&#xff09;會話窗口&#xff08;Session Windows&#xff09;全局窗口&#xff08;Global Windows&#xff09;窗口API概覽窗口函數增量聚合函數ReduceFun…

攻擊路徑(4):API安全風險導致敏感數據泄漏

本文是《攻防演練 | JS泄露到主機失陷[1]》的學習筆記&#xff0c;歡迎大家閱讀原文。攻擊路徑通過未授權訪問攻擊獲取敏感數據通過SQL注入攻擊獲取服務器權限通過憑據訪問攻擊獲取數據庫權限和敏感數據和應用權限安全風險與加固措施通過未授權訪問攻擊獲取敏感數據、通過SQL注…

機器學習面試題:請介紹一下你理解的集成學習算法

集成學習&#xff08;Ensemble Learning&#xff09;的核心思想是“集思廣益”&#xff0c;它通過構建并結合多個基學習器&#xff08;Base Learner&#xff09;來完成學習任務&#xff0c;從而獲得比單一學習器更顯著優越的泛化性能。俗話說&#xff0c;“三個臭皮匠&#xff…

Invalid bound statement (not found): com.XXX.XXx.service.xxx無法執行service

org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): com.xxx.xxx.service.CitytownService.selectCitytown 出現無法加載sevice層的時候&#xff0c;如下圖所示1&#xff0c;處理方法是&#xff0c;先看下注解MapperScan內的包地址&#xff0c…

泛型(Generics)what why when【前端TS】

我總是提醒自己一定要嚴謹嚴謹嚴謹 目錄TypeScript 泛型 (Generics)1. 什么是泛型&#xff1f;2. 為什么需要泛型&#xff1f;3. 泛型常見用法3.1 函數泛型3.2 接口泛型3.3 類泛型3.4 泛型約束3.5 泛型默認值3.6 多個泛型參數4. 泛型應用場景TypeScript 泛型 (Generics) 1. 什…

分布式協議與算法實戰-協議和算法篇

05丨Paxos算法&#xff08;一&#xff09;&#xff1a;如何在多個節點間確定某變量的值? 提到分布式算法&#xff0c;就不得不提 Paxos 算法&#xff0c;在過去幾十年里&#xff0c;它基本上是分布式共識的代名詞&#xff0c;因為當前最常用的一批共識算法都是基于它改進的。比…

9.13 9.15 JavaWeb(事務管理、AOP P172-P182)

事務管理事務概念事務是一組操作的集合&#xff0c;是一個不可分割的工作單位&#xff0c;這些操作要么同時成功&#xff0c;要么同時失敗操作開啟事務&#xff08;一組操作開始前&#xff0c;開啟事務&#xff09;&#xff1a;start transaction / begin提交事務&#xff08;這…

檢索融合方法- Distribution-Based Score Fusion (DBSF)

在信息檢索&#xff08;IR&#xff09;、推薦系統和多模態檢索中&#xff0c;我們常常需要融合來自多個檢索器或模型的結果。不同檢索器可能對同一文檔打出的分數差異很大&#xff0c;如果直接簡單加權&#xff0c;很容易出現某個檢索器“主導融合結果”的情況。 Distribution…

Oracle體系結構-歸檔日志文件(Archive Log Files)

核心概念&#xff1a;什么是歸檔日志文件&#xff1f; 定義&#xff1a; 歸檔日志文件&#xff08;Archive Log Files&#xff09;是在線重做日志文件&#xff08;Online Redo Log Files&#xff09;在被覆蓋之前的一個完整副本。它們由 Oracle 的后臺進程 ARCn&#xff08;歸檔…

GoogLeNet實戰:用PyTorch實現經典Inception模塊

配套筆記&講解視頻&#xff0c;點擊文末名片獲取研究背景&#xff08;Background&#xff09; 1.1 領域現狀&#xff08;大環境與挑戰&#xff09; 想象一下&#xff0c;你和朋友們在看一大堆照片——貓、狗、汽車、蛋糕&#xff0c;大家要把每張照片貼上標簽。幾年前&…

【開題答辯全過程】以 “舊書驛站”微信小程序的設計與開發為例,包含答辯的問題和答案

個人簡介一名14年經驗的資深畢設內行人&#xff0c;語言擅長Java、php、微信小程序、Python、Golang、安卓Android等開發項目包括大數據、深度學習、網站、小程序、安卓、算法。平常會做一些項目定制化開發、代碼講解、答辯教學、文檔編寫、也懂一些降重方面的技巧。感謝大家的…

【辦公類-112-01】20250912家園每周溝通指導(Deepseek擴寫完善+Python模擬點擊鼠標自動發送給家長微信)

背景需求 孩子剛上小班,家長比較關心孩子情況(情緒、社交、吃飯等) 所以我每周五晚上和家長溝通一下孩子的情況。 操作流程 第一周(9月5日)是“適應周”,我添加了所有孩子的一位家長的微信號 23份全部是手打,足足寫了4個小時。第一周案例多,所以寫了很多,措辭醞釀后…

Spark專題-第一部分:Spark 核心概述(1)-Spark 是什么?

眾所周知&#xff0c;教學文檔總該以理論部分作為開篇&#xff0c;于是我們這篇Spark專題同樣會以一堆理論和專有名詞開始&#xff0c;筆者會盡可能的讓專業詞匯通俗易懂 第一部分&#xff1a;Spark 核心概述 Spark 是什么&#xff1f; 1. 大數據時代的"超級賽車"…

從零到一上手 Protocol Buffers用 C# 打造可演進的通訊錄

一、為什么是 Protobuf&#xff08;而不是 XML/自定義字符串/.NET 二進制序列化&#xff09; 在需要把結構化對象持久化或跨進程/跨語言傳輸時&#xff0c;常見方案各有痛點&#xff1a; BinaryFormatter 等 .NET 二進制序列化&#xff1a;對類型簽名與版本極其脆弱、體積偏大&…

計算機網絡(三)網絡層

三、網絡層網絡層是五層模型中的第三層&#xff0c;位于數據鏈路層和傳輸層之間。它的核心任務是實現數據包在不同網絡之間&#xff08;跨網絡&#xff09;的邏輯傳輸。網絡層的數據傳輸單位是數據報&#xff08;Datagram&#xff09;或數據包&#xff08;Packet&#xff09;。…

互聯網大廠Java面試實錄:從基礎到微服務全棧技術答疑

互聯網大廠Java面試實錄&#xff1a;從基礎到微服務全棧技術答疑 本文以電商場景為背景&#xff0c;展現一場互聯網大廠Java開發職位的面試過程。嚴肅的面試官與搞笑的水貨程序員謝飛機展開三輪技術問答&#xff0c;涵蓋Java SE、Spring Boot、數據庫、微服務、安全以及CI/CD等…

StringBuilder 深度解析:數據結構與擴容機制的底層細節

文章目錄 前言 一、數據結構&#xff1a;不止是簡單的字符數組 1. 核心成員變量&#xff08;定義在 AbstractStringBuilder 中&#xff09; 2. 構造器與初始容量 二、擴容機制&#xff1a;從 "不夠用" 到 "換大容器" 的全過程 步驟 1&#xff1a;計算…