基于C++11 CPU多线程的 奇偶排序(没有CUDA)
2017-01-14 21:51
429 查看
写的不一定对!错了求指正!
编译大概是
其实还没学c++14
最近开始学CUDA,感觉线程具体怎么用和硬件是直接相关的, 不同架构啊不同精度啊使用线程的方式都应该不同。这篇博客就是个实验,用CPU实现一下奇偶排序为日后与CUDA做比较
一直是CPU和GPU一起学的。二者都支持多线程,但是并不是一种线程。CPU线程更适合粗粒度的任务,而GPU线程更适合细粒度的任务。而且CUDA最小调度单位是线程束(warp).
CPU线程的创建,销毁,切换,还是比较花时间的。也就是奇偶排序不太适合CPU多线程的原因.N厂GPU每个线程都有自己的寄存器,这就很厉害了,完全就没有上下文切换的开销,就只要轻轻拨一下开关。CUDA编程一个思路就是用海量线程去掩盖访存延迟。
图片来自wiki,奇偶排序的过程
学习了算法课的精神,特地与vanilla quick sort,bubble sort 做比较并计时(其实没必要,奇偶排序实在太慢= =)
vanilla quick sort 0.002025s
odd even sort 857.425s
LEN = 1000
vanilla quick sort 0.000101s
odd even sort 8.55487s
LEN = 100
vanilla quick sort 5e-06s
bubble sort 2.5e-05s
odd even sort 0.072577s
前言
这篇是用C++11 的 thread 做的。编译大概是
g++ sort.cpp -O3 -pthread -std=c++14 -o sort
其实还没学c++14
最近开始学CUDA,感觉线程具体怎么用和硬件是直接相关的, 不同架构啊不同精度啊使用线程的方式都应该不同。这篇博客就是个实验,用CPU实现一下奇偶排序为日后与CUDA做比较
一直是CPU和GPU一起学的。二者都支持多线程,但是并不是一种线程。CPU线程更适合粗粒度的任务,而GPU线程更适合细粒度的任务。而且CUDA最小调度单位是线程束(warp).
CPU线程的创建,销毁,切换,还是比较花时间的。也就是奇偶排序不太适合CPU多线程的原因.N厂GPU每个线程都有自己的寄存器,这就很厉害了,完全就没有上下文切换的开销,就只要轻轻拨一下开关。CUDA编程一个思路就是用海量线程去掩盖访存延迟。
奇偶排序
奇偶排序思路不太难,本来就是为了并行而设计的算法。拆问题的时候就是把数据用奇偶隔开,开差不多数组长度一半数量的线程去和相邻比较。假设能够任意线程数地并行的话,那么只需要:偶比较一次,奇比较一次,偶。。。。直到完全有序 设一个flag来表示是否完成排序。图片来自wiki,奇偶排序的过程
学习了算法课的精神,特地与vanilla quick sort,bubble sort 做比较并计时(其实没必要,奇偶排序实在太慢= =)
测试结果
LEN = 10000vanilla quick sort 0.002025s
odd even sort 857.425s
LEN = 1000
vanilla quick sort 0.000101s
odd even sort 8.55487s
LEN = 100
vanilla quick sort 5e-06s
bubble sort 2.5e-05s
odd even sort 0.072577s
主要代码
bool Sorted = false; template<typename T=int> void sortswap(T* data,int index,int right) { if(index == right) return; if(data[index]>data[index+1]) { swap(data[index],data[index+1]); Sorted = false; } } template<typename T=int> void oddEvenSort(T* data,int left = 0,int right = LEN-1) { int latch = (right-left)/2 + (right-left)%2; thread threads[latch]; int start = left; while(!Sorted) { Sorted = true; for(int i = start,j = 0;j<latch;i+=2,j++) threads[j] = thread(sortswap<T>,data,i,right); for(int i = 0;i<latch;i++) threads[i].join(); if(start == left) start = left +1; else start = left; } }
全部代码
#include<thread>
#include<atomic>
#include<ctime>
#include<iostream>
#include<ctime>
#include<cstdlib>
using namespace std;
using TYPE = int;
const int LEN = 100;
TYPE* data = new TYPE[LEN];
template<typename T=int>
void disp(T* data,int l)
{
// cout<<__func__<<": ";
for(int i = 0;i<l;i++)
{
if((i!=0) && (i%10==0))
cout<<endl;
cout<<data[i]<<" ";
}
cout<<endl;
}
template<typename T=int>
void init(T* data,int len)
{
srand(unsigned(time(0)));
for(int i = 0;i<len;i++)
data[i] = (T)rand();
}
template<typename T=int>
void bubbleSort(T* data,int left = 0,int right = LEN-1)
{
for(int i = left; i < right; i++)
for (int j = i + 1; j < right; j++)
if (data[i] > data[j])
swap(data[i], data[j]);
}
template<typename T=int>
void qsort(T* data,int left = 0,int right = LEN-1)
{
if(left < right)
{
int l = left;
int h = right;
T pivot = data[left];
while(l<h)
{
while(data[h] >= pivot && l < h) h--;
data[l] = data[h];
while(data[l]<pivot && l < h) l++;
data[h] = data[l];
}
data[l] = pivot;
qsort(data,left,l-1);
qsort(data,l+1,right);
}
}
bool Sorted = false; template<typename T=int> void sortswap(T* data,int index,int right) { if(index == right) return; if(data[index]>data[index+1]) { swap(data[index],data[index+1]); Sorted = false; } } template<typename T=int> void oddEvenSort(T* data,int left = 0,int right = LEN-1) { int latch = (right-left)/2 + (right-left)%2; thread threads[latch]; int start = left; while(!Sorted) { Sorted = true; for(int i = start,j = 0;j<latch;i+=2,j++) threads[j] = thread(sortswap<T>,data,i,right); for(int i = 0;i<latch;i++) threads[i].join(); if(start == left) start = left +1; else start = left; } }
template<typename T>
void (*f[])(T*,int,int) =
{
qsort,
bubbleSort,
oddEvenSort
};
int main()
{
for(int i = 0;i<3;i++)
{
init<TYPE>(data,LEN);
auto t1 = clock();
f<TYPE>[i](data,0,LEN-1);
cout<<(double)(clock()-t1)/CLOCKS_PER_SEC<<endl;
}
return 0;
}
相关文章推荐
- C++基础——1.变量和基本类型(基于c++11)
- 基于C++11的阻塞队列简单实现
- ubuntu16.04+cuda8.0+cudnn5.1+caffe 安装(基于独立主机&集成显卡>X1080Ti)
- C++11 学习笔记 基于范围的for循环
- 基于Windows的CUDA安装 (Setup CUDA on Windows)
- 基于框架的开发就没有学习价值吗
- 基于CUDA的GPU优化建议
- 【网络编程】半同步--半异步线程池源码分析之任务队列(基于C++11)
- 基于CUDA实现Ray-Casting
- CUDA C 编程权威指南 学习笔记:第一章 基于CUDA的异构并行计算
- (OK) port_php-5.6.14_to_Android—(和lighttpd集成成功)—没有基于android 4.4源码
- 基于C++11的线程池,简洁且可以带任意多的参数
- 基于c++11的短小精悍生产者消费者模型
- 基于CUDA的光线跟踪算法
- 基于C++11的线程池
- GPU中基于CUDA计算SM中active block和active warp及普遍优化流程
- 最简单的基于Tomcat的Web应用程序-没有Servlet,只访问静态资源(jsp,html,gif等)
- 没有网络,也能上网-基于USSD技术的信息服务
- C++11特性:auto关键字与基于范围的for循环