Opencl 并行求和

上周尝试用opencl求极大值,在网上查到大多是求和,所谓的reduction算法。不过思路是一样的。

CPP:


   int err = 0;
unsigned long int nNumCount = 102400000;
int nLocalSize = 256;
int nGroupSize = 102400;
int nGroup = nGroupSize / nLocalSize;

int* pArray = new int[nNumCount];
unsigned long int nReal = 0;
int nStart = GetTickCount();
for (int i=0;i<nNumCount;++i)
{
pArray[i] = i*2;
nReal += pArray[i];
}
cout<<GetTickCount() - nStart<<endl;

cl_mem clmemArray = clCreateBuffer(context,CL_MEM_READ_WRITE,sizeof(int) * nNumCount,NULL,NULL);
err = clEnqueueWriteBuffer(queue,clmemArray,CL_TRUE,0,sizeof(int)*nNumCount,pArray,0,0,0);
cl_mem clmemRes = clCreateBuffer(context,CL_MEM_READ_WRITE,sizeof(int) * nGroup,NULL,NULL);

nStart = GetTickCount();

err = clSetKernelArg(m_KerCalcRay,0,sizeof(cl_mem),&clmemArray);
err = clSetKernelArg(m_KerCalcRay,1,sizeof(cl_mem),&clmemRes);
err = clSetKernelArg(m_KerCalcRay,2,sizeof(int)*nLocalSize,0);
err = clSetKernelArg(m_KerCalcRay,3,sizeof(int),&nNumCount);

size_t localws[1] = {nLocalSize};
size_t globalws[1] = {nGroupSize};

err = clEnqueueNDRangeKernel(queue,m_KerCalcRay,1,NULL,globalws,localws,0,NULL,NULL);
clFinish(queue);

int* pRes = new int[nGroup];
err = clEnqueueReadBuffer(queue,clmemRes,CL_TRUE,0,sizeof(int)*nGroup,pRes,0,0,0);
clFinish(queue);

unsigned long int nRes = 0;
for(int i=0;i<nGroup;++i)
{
nRes += pRes[i];
}
  assert(nRes == nReal);

kernel:


__kernel void ReduceSum(__global int* num,__global int* res,__local int* pData,int nCount)
{
unsigned int tid = get_local_id(0);
unsigned int bid = get_group_id(0);
unsigned int gid = get_global_id(0);
unsigned int localSize = get_local_size(0);
unsigned int globalSize = get_global_size(0);

int nRes = 0;
while(gid < nCount)
{
nRes += num[gid];
gid += globalSize;
}
pData[tid] = nRes;
barrier(CLK_LOCAL_MEM_FENCE);

// do reduction in shared mem
for(unsigned int s = localSize >> 1; s > 0; s >>= 1)
{
if(tid < s)
{
pData[tid] += pData[tid + s];
}
barrier(CLK_LOCAL_MEM_FENCE);
}

if(tid == 0)
res[bid] = pData[0];

}

Reduction求和是这样一种方法,比如8个数0到7依次存放,求和的时候就是下标0和4、1和5、2和6、3和7,求和结果放到下标0、1、2、3中(同步一把barrier(CLK_LOCAL_MEM_FENCE))。然后继续就是0和2,、1和3求和结果放到0、1中。如此往复、最终结果就放到下标0中啦。

另:我试过循环展开减少同步次数、不过效率增长微乎其微。

时间: 2024-12-20 22:39:54

Opencl 并行求和的相关文章

使用分支/合并框架执行并行求和

分支/合并框架 ? 分支/合并框架的目的是以递归方式将可以并行的任务拆分成更小的任务,然后将每个子任 务的结果合并起来生成整体结果.它是ExecutorService接口的一个实现,它把子任务分配给 线程池(称为ForkJoinPool)中的工作线程.首先来看看如何定义任务和子任务. 使用RecursiveTask ? 要把任务提交到这个池,必须创建RecursiveTask的一个子类,其中R是并行化任务(以 及所有子任务)产生的结果类型,或者如果任务不返回结果,则是RecursiveActio

Python的并行求和例子

先上一个例子,这段代码是为了评估一个预测模型写的,详细评价说明在 https://www.kaggle.com/c/how-much-did-it-rain/details/evaluation, 它的核心是要计算 在实际计算过程中,n很大(1126694),以至于单进程直接计算时间消耗巨大(14分10秒), 所以这里参考mapReduce的思想,尝试使用多进程的方式进行计算,即每个进程计算一部分n,最后将结果相加再计算C 代码如下: import csv import sys import l

并行求和

1 #include <vector> 2 #include <iostream> 3 #include <thread> 4 #include <mutex> 5 6 using namespace std; 7 8 int psum[256]; 9 std::mutex g_mtx; 10 int g_sum = 0; 11 12 void add0(int vargp, int var_first, int var_end) 13 { 14 for (

CUDA和OpenCL异同点比较

CUDA和OpenCL异同点比较 一.概述 对CUDA和opencl有一定的编程经验,但是细心的人可以发现,OPENCL就是仿照CUDA来做的.既然两个GPU的编程框架如此相像,那么他们究竟有什么不同呢?下面就一一道来. 二.数据并行的模型 OpenCL采用的数据并行模型就是采用CUDA的数据并行模型.下面的表格反应了CUDA和opencl并行模型之间的映射关系. OpenCL CUDA Kernel函数 Kernel函数 主机程序 主机程序 N-DRange 网格 工作项 线程 工作组 线程块

CUDA学习:第一CUDA代码:数组求和

今天有些收获了,成功运行了数组求和代码:就是将N个数相加求和 //环境:CUDA5.0,vs2010 #include "cuda_runtime.h"#include "device_launch_parameters.h" #include <stdio.h> cudaError_t addWithCuda(int *c, int *a); #define TOTALN 72120#define BLOCKS_PerGrid 32#define TH

CUDA学习:进一步理解块、线程

1. CUDA里的块和线程概念可以用下面的图来表示: 每个grid里包含可以用二维数组表示的block(块),每个block又包含一个可以用二维数组表示的thread(线程). 2.  二维数组块和线程可以用dim3来定义: dim3 blockPerGrid(3,2); //定义了3*2=6个blocks dim3 threadsPerBlock(3,3);//定义了3*3=9个threads 3. 运行时每个线程的代码,如何知道自己是在哪个块里的哪个线程中运行呢?通过下面的变量计算: * 块

[Berkeley]弹性分布式数据集RDD的介绍(RDD: A Fault-Tolerant Abstraction for In-Memory Cluster Computing 论文翻译)

摘要: 本文提出了分布式内存抽象的概念--弹性分布式数据集(RDD,Resilient Distributed Datasets).它同意开发者在大型集群上运行基于内存的计算.RDD适用于两种应用,而现有的数据流系统对这两种应用的处理并不高效:一是迭代式算法,这在图应用和机器学习领域非经常见.二是交互式数据挖掘工具.这两种情况下.将数据保存在内存中可以极大地提高性能.为了有效地实现容错,RDD提供了一种高度受限的共享内存,即RDD在共享状态的时候是基于粗粒度的转换而不是细粒度的更新(换句话说就是

Hadoop与Spark比较

先看这篇文章:http://www.huochai.mobi/p/d/3967708/?share_tid=86bc0ba46c64&fmid=0 直接比较Hadoop和Spark有难度,因为它们处理的许多任务都一样,但是在一些方面又并不相互重叠. 比如说,Spark没有文件管理功能,因而必须依赖Hadoop分布式文件系统(HDFS)或另外某种解决方案. Hadoop框架的主要模块包括如下: Hadoop Common Hadoop分布式文件系统(HDFS) Hadoop YARN Hadoop

C语言处理CSV数据

以下代码为博客 <Python的并行求和例子>: http://www.cnblogs.com/instant7/p/4312786.html 中并行python代码的C语言重写版. 用C来跑一遍单线程也只需要50秒,比python 开4进程的实现要快6倍多,CPU占用率也只用python的1/4. 看来计算密集型应用还是需要用这些不顺手的老古董来弄的:) #include <stdio.h> #include <string.h> #include <iostr