cuda gpu CTAMergesort
来源:互联网 发布:php文件上传过程 编辑:程序博客网 时间:2024/05/21 05:20
注:下面所提到的代码实现,均在moderngpu2.0中被作者所重写。
gpu上-并行归并排序,modern gpu上CTAMergesort源码实现:
template<int NT, int VT, bool Stable, bool HasValues, typename KeyType,
typename ValType, typename Comp>
MGPU_DEVICE void CTAMergesort(KeyType threadKeys[VT], ValType threadValues[VT],
KeyType* keys_shared, ValType* values_shared, int count, int tid,
Comp comp) {
// Stable sort the keys in the thread.
if(VT * tid < count) {
if(Stable)
OddEvenTransposeSort<VT>(threadKeys, threadValues, comp);
else
OddEvenMergesort<VT>(threadKeys, threadValues, comp);
}
// Store the locally sorted keys into shared memory.
DeviceThreadToShared<VT>(threadKeys, tid, keys_shared);
// Recursively merge lists until the entire CTA is sorted.
CTABlocksortLoop<NT, VT, HasValues>(threadValues, keys_shared,
values_shared, tid, count, comp);
}
该方法的实现逻辑:
1.将要排序的数据列表,先将每个线程自己要排序的数据存储到线程本地变量上(寄存器上)
2.每个线程先使用奇偶排序排序本地变量数据。
3.将本地排序好的变量数据,统一存放会原来共享内存的对应位置上,供下面CTABlocksortLoop进行最终数据的排序(共享内存的数据是SM内的所有线程共享的,而SM是以block进行统一调度的,即该排序是block级别的排序)
4.CTABlocksortLoop协调每个线程自己的排序工作。
CTABlocksortLoop源码:
template<int NT, int VT, bool HasValues, typename KeyType, typename ValType,
typename Comp>
MGPU_DEVICE void CTABlocksortLoop(ValType threadValues[VT],
KeyType* keys_shared, ValType* values_shared, int tid, int count,
Comp comp) {
#pragma unroll
for(int coop = 2; coop <= NT; coop *= 2) {
int indices[VT];
KeyType keys[VT];
CTABlocksortPass<NT, VT>(keys_shared, tid, count, coop, keys,
indices, comp);
if(HasValues) {
// Exchange the values through shared memory.
DeviceThreadToShared<VT>(threadValues, tid, values_shared);
DeviceGather<NT, VT>(NT * VT, values_shared, indices, tid,
threadValues);
}
// Store results in shared memory in sorted order.
DeviceThreadToShared<VT>(keys, tid, keys_shared);
}
}
coop为线程合作数,且每个线程各自排序的数据为VT数据量。
每一次迭代结束,均表明每一块为coop * VT的数据均是排序好的数据。
CTABlocksortPass源码实现:
template<int NT, int VT, typename T, typename Comp>
MGPU_DEVICE void CTABlocksortPass(T* keys_shared, int tid, int count,
int coop, T* keys, int* indices, Comp comp) {
int list = ~(coop - 1) & tid;
int diag = min(count, VT * ((coop - 1) & tid));
int start = VT * list;
int a0 = min(count, start);
int b0 = min(count, start + VT * (coop / 2));
int b1 = min(count, start + VT * coop);
int p = MergePath<MgpuBoundsLower>(keys_shared + a0, b0 - a0,
keys_shared + b0, b1 - b0, diag, comp);
SerialMerge<VT, true>(keys_shared, a0 + p, b0, b0 + diag - p, b1, keys,
indices, comp);
}
这段代码便是能够使多个线程能并行排序各自的数据,并且各自数据排序完后,相关联的线程下的数据便是连续有序的数据了。这听起来有点神奇。
这里有点注明下,假设现在有N段的已经排序好的数据,那么需要将数据合并成N/2端排序好的数据,即需要将相邻的两端排序好的数据进行合并工作,而每每两段的合并工作的
协作线程数便是coop。也就是不管协调线程数coop不管有多少,其所负责的都只是2相邻两端的排序好的数据,也就是说我们需要将这两端的合并排序的工作,平分给这coop个线程。
下面便说这段代码是如何做到的,其实这里用到了
Merge Path-Parallel Merging Made Simple,有兴趣的可以去搜搜看具体内容。
keys_shared + b0, b1 - b0, diag, comp);
indices, comp);
- cuda gpu CTAMergesort
- GPU & CUDA
- GPU&CUDA
- gpu/cuda-03-cuda memory
- NVIDIA-GPU-CUDA
- GPU-CUDA学习方法求教
- GPU-cuda编程葵花宝典
- GPU---CUDA安装
- GPU硬件结构--CUDA
- Using+GPU+with+Cuda
- 基于GPU的CUDA
- GPU and CUDA
- GPU和CUDA介绍
- cuda gpu查询缓慢
- CUDA on NVIDIA GPU
- GPU&CUDA几个基本概念
- 【转】CUDA-GPU架构
- CUDA 和 GPU
- "汉诺塔"算法-之通俗易懂,简单的原理-java编程
- mysql 入门基础(5)—存储过程和游标
- appcan中的微信分享与qq分享
- MongoDB:[HostnameCanonicalizationWorker] Failed to obtain address information for hostname
- MySQL环境部署
- cuda gpu CTAMergesort
- ubuntu下使用Qt 编译时cannot find -lGL错误解决
- 网卡、网关、网桥、集线器、中继器、交换机、路由器
- 上帝与集合的正确用法 [Bzoj 3884]
- CentOS上安装Mplayer播放器
- java.util.Arrays类
- Android 带清除功能的输入框控件ClearEditText,仿IOS的输入框
- C#winform直接连接SQL数据库mdf文件
- 【STL源码剖析】__type_traits技法