首页 > 编程语言 >OpenCL规约算法例子

OpenCL规约算法例子

时间:2024-02-13 21:13:17浏览次数:31  
标签:temp cl 规约 OpenCL unsigned halfSize int 算法 CPU

本文给出一个规约算法求数组的和的例子。本例子求20000000(两千万)个整数的和。运算过程分成了两步,第一步是GPU对每一个工作组内规约求和,然后将每个工作组的求和结果放到数组中输出。第二步是对输出的数组用CPU求和。实际运行对比发现GPU的效率不如用CPU直接求和。下述算法运行环境是VS2015、OpenCL3,CPU是AMD A4-9125,显卡就是CPU自带的核芯显卡。

本例不需要头文件,下面是CPP文件:

const string kernel = u8R"(
    kernel void reduceSum(global int* num, global int* result, int nCount)
    {
        unsigned int lid = 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); 
        local int pData[1024];
    
        pData[lid] = num[gid];    
        barrier(CLK_LOCAL_MEM_FENCE);

        unsigned int halfSize = localSize;
        while (halfSize > 1) 
        {
            unsigned int odd = halfSize & 1;
            halfSize >>= 1;
            unsigned int lastIndex = halfSize - 1;
            if (lid <= lastIndex) 
            {
                pData[lid] += pData[lid + halfSize];
            }
            if (lid == lastIndex && odd == 1)
            {
                pData[lid] += pData[lid + halfSize + 1];
            }
            barrier(CLK_LOCAL_MEM_FENCE);
        }
    
        if (lid == 0)
        {
            result[bid] = pData[0];
        }
    })";

void main()
{
    cl::Program program(kernel);
    try {
        program.build("-cl-std=CL3.0");
    }
    catch (...) {
        cl_int buildErr = CL_SUCCESS;
        auto buildInfo = program.getBuildInfo<CL_PROGRAM_BUILD_LOG>(&buildErr);
        for (auto &pair : buildInfo) {
            std::cerr << pair.second << std::endl << std::endl;
        }
    }

    int64 t1, t2;
    t1 = getTickCount();

    auto kernelFunc = cl::KernelFunctor<cl::Buffer, cl::Buffer, int>(program, "reduceSum");
    vector<int> array1(20000000, 1);
    vector<int> temp(100000, 0);
    array1[32] = 100;
    cl::Buffer inputBuffer(array1.begin(), array1.end(), true);
    cl::Buffer outputBuffer(temp.begin(), temp.end(), false);
    kernelFunc(cl::EnqueueArgs(cl::NDRange(20000000), cl::NDRange(200)), inputBuffer, outputBuffer, 20000000);
    cl::copy(outputBuffer, temp.begin(), temp.end());
    int sum1 = std::accumulate(temp.begin(), temp.end(), 0);

    t2 = getTickCount();
    cout << (t2 - t1) / getTickFrequency() * 1000 << "ms" << endl;

    vector<int> array2(20000000, 1);
    array2[32] = 100;

    t1 = getTickCount();

    int sum2 = std::accumulate(array2.begin(), array2.end(), 0);

    t2 = getTickCount();
    cout << (t2 - t1) / getTickFrequency() * 1000 << "ms" << endl;

    int c;
    cin >> c;
}

上述代码的核函数考虑了工作组大小在规约过程中变成奇数的可能。因此用变量odd判断此时的数组大小是否为奇数,对应地做特殊处理(即加上末尾多出来的1个数)。在Release版下测试,GPU速度远低于CPU。我学艺不精,不会优化这种简单的运算,不能让GPU速度快于CPU速度,敬请谅解。

另外,此代码在用Qt调试过程中出现使Qt程序无法关闭的情况,数据正常也没有死循环,暂时不知道为什么。在控制台程序中调试程序可以正常退出。

标签:temp,cl,规约,OpenCL,unsigned,halfSize,int,算法,CPU
From: https://www.cnblogs.com/mengxiangdu/p/17908342.html

相关文章

  • 2024牛客寒假算法基础集训营3
    M题智乃的36倍数(normalversion)错解幂运算写成了乘~#include<bits/stdc++.h>usingnamespacestd;#defineendl'\n'#defineintlonglong#definedebug(x)cout<<x<<""<<endl;#define_debug(a,n)for(inti=0;i<n;i++)......
  • 2024牛客寒假算法基础集训营1
    2024牛客寒假算法基础集训营1A解题思路:按照\(dfs\)出现顺序暴力判断即可。代码:#include<bits/stdc++.h>usingnamespacestd;usingll=longlong;usingpii=pair<ll,ll>;#definefifirst#definesesecondusingi128=__int128_t;usingpiii=pair<ll,pai......
  • boruvka 算法学习笔记
    boruvka算法就是最小生成树B算法。B算法的思路是每次对每个连通块,求出它能连出去的权值最小的边,然后再按边权从小到大合并。由于每次操作连通块数至少减半,所以复杂度是\(O(m\logn)\)。1.CF1305GKuroniandAntihype题意:长为\(n\)的数列\(a\),现在要选择全部数,每一次你......
  • 微分积分及其运算法则成对列举
         ......
  • 【算法】排序
    冒泡排序思想:每一轮确定一个最大值移到最右边。点击查看代码for(inti=n;i>=1;i--){ for(intj=1;j<i;j++){ if(a[j]>a[j+1])swap(a[j],a[j+1]); } }选择排序思想:与冒泡相似。点击查看代码for(inti=n;i>=1;i--){ intmax_id......
  • 2024牛客寒假算法基础集训营2个人补题题解(K、D)
    比赛链接:2024牛客寒假算法基础集训营2K、TokitsukazeandPassword(easy)题面看着很难实际上只要暴力的东西,赛时看了眼题面就溜了血亏爆搜,枚举\(abcd\)和_可能的值,枚举的情况只有\(9*8*7*6*9=27216\)种。判断按照枚举出的对应值排列出的密码是否满足条件,满足就\(ans++\)写完......
  • [数据结构] 串与KMP算法详解
    写在前面今天是农历大年初三,祝大家新年快乐!尽管新旧交替只是一个瞬间,在大家互祝新年快乐的瞬间,在时钟倒计时数到零的瞬间,在烟花在黑色幕布绽放的瞬间,在心底默默许下愿望的瞬间……跨入新的一年,并不意味了一切都会朝着更美好,也没有什么会从天而降,我们赋予了它这份意义,让它自然裹......
  • 有关素数的算法
    一、素性判断素数,又叫质数,是指一个整数,除了1和本身之外,还有其它的因数(注意:1不是素数)。因此,对于一个整数\(n\),我们只要检测\([2,n-1]\)能否整除\(n\)。整除的定义:\(\exist\)\(a,b,k\in\mathbb{Z}\),使得\(a=kb\),则称\(b\)整除\(a\),记\(b\)\(|\)\(a\)。若\(......
  • 我在代码随想录|写代码| 贪心算法 | 理论基础, 455.分发饼干, 376. 摆动序列,53. 最大
    学习目标:博主介绍:27dCnc专题:数据结构帮助小白快速入门......
  • 在k8S中,Scheduler使用哪两种算法将Pod绑定到worker节点?
    在Kubernetes(k8S)中,Scheduler使用两种主要的算法阶段来决定将Pod绑定到哪个worker节点上:预选算法(Predicates)预选阶段的主要目标是过滤掉不满足调度条件的节点。Scheduler会根据一系列预定义的预选策略对所有可用节点进行筛选。这些策略可能包括但不限于:检查节点上的资源是否......