性能:boost.compute vs. opencl C++ 包装器

2024-01-11

以下代码分别使用 boost.compute 和 opencl C++ 包装器将两个向量相加。结果显示 boost.compute 几乎比 opencl c++ 包装器慢 20 倍。我想知道我是否错过了使用 boost.compute 或者它确实很慢。 平台:win7、vs2013、boost 1.55、boost.compute 0.2、ATI Radeon HD 4600

代码使用 C++ 包装器:

#define __CL_ENABLE_EXCEPTIONS
#include <CL/cl.hpp>
#include <boost/timer/timer.hpp>
#include <boost/smart_ptr/scoped_array.hpp>
#include <fstream>
#include <numeric>
#include <algorithm>
#include <functional>

int main(){
    static char kernelSourceCode[] = "\
__kernel void vadd(__global int * a, __global int * b, __global int * c){\
    size_t i = get_global_id(0);\
    \
    c[i] = a[i] + b[i];\
    }\
";

    using type = boost::scoped_array<int>;
    size_t const BUFFER_SIZE = 1UL << 13;
    type A(new int[BUFFER_SIZE]);
    type B(new int[BUFFER_SIZE]);
    type C(new int[BUFFER_SIZE]);

    std::iota(A.get(), A.get() + BUFFER_SIZE, 0);
    std::transform(A.get(), A.get() + BUFFER_SIZE, B.get(), std::bind(std::multiplies<int>(), std::placeholders::_1, 2));

    try {
        std::vector<cl::Platform> platformList;
        // Pick platform
        cl::Platform::get(&platformList);
        // Pick first platform
        cl_context_properties cprops[] = {
            CL_CONTEXT_PLATFORM,
            (cl_context_properties)(platformList[0])(),
            0
        };
        cl::Context context(CL_DEVICE_TYPE_GPU, cprops);
        // Query the set of devices attached to the context
        std::vector<cl::Device> devices = context.getInfo<CL_CONTEXT_DEVICES>();
        // Create command-queue
        cl::CommandQueue queue(context, devices[0], 0);
        // Create the program from source
        cl::Program::Sources sources(
            1,
            std::make_pair(kernelSourceCode, 0)
            );
        cl::Program program(context, sources);
        // Build program
        program.build(devices);
        // Create buffer for A and copy host contents
        cl::Buffer aBuffer = cl::Buffer(
            context,
            CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR,
            BUFFER_SIZE * sizeof(int),
            (void *)&A[0]);
        // Create buffer for B and copy host contents
        cl::Buffer bBuffer = cl::Buffer(
            context,
            CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR,
            BUFFER_SIZE * sizeof(int),
            (void *)&B[0]);
        // Create buffer that uses the host ptr C
        cl::Buffer cBuffer = cl::Buffer(
            context,
            CL_MEM_READ_WRITE | CL_MEM_USE_HOST_PTR,
            BUFFER_SIZE * sizeof(int),
            (void *)&C[0]);
        // Create kernel object
        cl::Kernel kernel(program, "vadd");
        // Set kernel args
        kernel.setArg(0, aBuffer);
        kernel.setArg(1, bBuffer);
        kernel.setArg(2, cBuffer);
        // Do the work
        void *output;
        {
            boost::timer::auto_cpu_timer timer;
            queue.enqueueNDRangeKernel(
                kernel,
                cl::NullRange,
                cl::NDRange(BUFFER_SIZE),
                cl::NullRange
                );
            output = (int *)queue.enqueueMapBuffer(
                cBuffer,
                CL_TRUE, // block
                CL_MAP_READ,
                0,
                BUFFER_SIZE * sizeof(int)
                );
        }
        std::ofstream gpu("gpu.txt");
        for (int i = 0; i < BUFFER_SIZE; i++) {
            gpu << C[i] << " ";
        }
        queue.enqueueUnmapMemObject(
            cBuffer,
            output);
    }
    catch (cl::Error const &err) {
        std::cerr << err.what() << "\n";
    }

    return EXIT_SUCCESS;
}

代码使用boost.compute:

#include <boost/compute/container/mapped_view.hpp>
 #include <boost/compute/algorithm/transform.hpp>
 #include <boost/compute/functional/operator.hpp>
 #include <numeric>
 #include <algorithm>
 #include <functional>
 #include <boost/timer/timer.hpp>
 #include <boost/smart_ptr/scoped_array.hpp>
 #include <fstream>
 #include <boost/tuple/tuple_comparison.hpp>

 int main(){
     size_t const BUFFER_SIZE = 1UL << 13;
     boost::scoped_array<int> A(new int[BUFFER_SIZE]), B(new int[BUFFER_SIZE]), C(new int[BUFFER_SIZE]);

     std::iota(A.get(), A.get() + BUFFER_SIZE, 0);
     std::transform(A.get(), A.get() + BUFFER_SIZE, B.get(), std::bind(std::multiplies<int>(), std::placeholders::_1, 2));

     try{
         if (boost::compute::system::default_device().type() != CL_DEVICE_TYPE_GPU){
             std::cerr << "Not GPU\n";
         }
         else{
             boost::compute::command_queue queue = boost::compute::system::default_queue();
             boost::compute::mapped_view<int> mA(static_cast<const int*>(A.get()), BUFFER_SIZE),
                 mB(static_cast<const int*>(B.get()), BUFFER_SIZE);
             boost::compute::mapped_view<int> mC(C.get(), BUFFER_SIZE);
             {
                 boost::timer::auto_cpu_timer timer;
                 boost::compute::transform(
                     mA.cbegin(), mA.cend(),
                     mB.cbegin(),
                     mC.begin(),
                     boost::compute::plus<int>(),
                     queue
                     );
                 mC.map(CL_MAP_READ, queue);
             }
             std::ofstream gpu("gpu.txt");
             for (size_t i = 0; i != BUFFER_SIZE; ++i) gpu << C[i] << " ";
             mC.unmap(queue);
         }
     }
     catch (boost::compute::opencl_error const &err){
         std::cerr << err.what() << "\n";
     }

     return EXIT_SUCCESS;
 }

生成的内核代码transform() http://kylelutz.github.io/compute/boost/compute/transform.htmlBoost.Compute 中的函数应该与您在 C++ 包装器版本中使用的内核代码几乎相同(尽管 Boost.Compute 会进行一些展开)。

您看到计时差异的原因是,在第一个版本中,您仅测量将内核排队并将结果映射回主机所需的时间。在 Boost.Compute 版本中,您还测量创建transform()内核,编译它,然后执行它。如果您想要更实际的比较,您应该测量第一个示例的总执行时间,包括设置和编译 OpenCL 程序所需的时间。

这种初始化损失(OpenCL 的运行时编译模型所固有的)在 Boost.Compute 中通过在运行时自动缓存已编译的内核(也可以选择离线缓存它们以便在下次运行程序时重用)而得到一定程度的缓解。呼唤transform()第一次调用后多次会快得多。

附:您也可以只使用 Boost.Compute 中的核心包装类(例如device http://kylelutz.github.io/compute/boost/compute/device.html and context http://kylelutz.github.io/compute/boost/compute/context.html)以及容器类(例如vector<T> http://kylelutz.github.io/compute/boost/compute/vector.html)并仍然运行您自己的自定义内核。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

性能:boost.compute vs. opencl C++ 包装器 的相关文章

  • 更新面板工作速度非常慢

    我正在编写一个用户可以注册的应用程序 注册时 可以选择多个选项 并根据这些注册字段可见或不可见以及是否必需 我想出了一个想法 所有字段都将位于 updatePanel 中 当用户更改注册选项时 我将在服务器端设置这些字段的可见性 它可以工作
  • 为什么这个 Web api 控制器不并发?

    我有一个 Web API 控制器 里面有以下方法 public string Tester Thread Sleep 2000 return OK 当我调用它 10 次 使用 Fiddler 时 我预计所有 10 次调用都会在大约 2 秒后
  • Exit() 时是否调用基本对象析构函数?

    我意识到这个问题已经出现过几次 但我试图获得上述问题的明确答案 但我不断遇到相互矛盾的信息 我需要知道的是 当我使用 exit 时 基本类对象是否被破坏 我知道需要删除动态内存 但我的意思更像是 include
  • 使用 CMake 时如何导出 Emscripten 中的 C 函数

    In 本教程 https emscripten org docs porting connecting cpp and javascript Interacting with code html interacting with code
  • Grpc - 将消息从一个客户端发送到连接到同一服务器的另一个客户端

    是否可以将消息从一个客户端发送到连接到同一服务器的另一个客户端 我想将数据从一个客户端发送到服务器然后发送到特定客户端 我想我需要获取客户端 ID 但我不知道如何获取此 ID 以及如何从服务器将此消息发送到该客户端 我这里有一个样本 这是一
  • 未找到 Boost 库,但编译正常

    我正在尝试在 C 中使用 boost 的文件系统 使用时看起来编译没问题 c c Analyse c o Analyse o g W Wall L usr local lib lboost filesystem lboost system
  • 循环遍历 C 结构中的元素以提取单个元素的值和数据类型

    我有一个要求 我有一个 C 语言的大结构 由大约 30 多个不同数据类型的不同元素组成 typedef struct type1 element1 type2 element2 type3 element3 type2 element4 1
  • 传递 constexpr 对象

    我决定给予新的C 14的定义constexpr旋转并充分利用它 我决定编写一个小的编译时字符串解析器 然而 我正在努力保持我的对象constexpr将其传递给函数时 考虑以下代码 include
  • 处理右值时的 insert 与 emplace

    std string myString std unordered set
  • 强制初始化模板类的静态数据成员

    关于模板类的静态数据成员未初始化存在一些问题 不幸的是 这些都没有能够帮助我解决我的具体问题的答案 我有一个模板类 它有一个静态数据成员 必须为特定类型显式实例化 即必须专门化 如果不是这种情况 使用不同的模板函数应该会导致链接器错误 这是
  • 在 .NET MAUI 中实现 TouchTracking

    我一直致力于将我们的应用程序从 Xamarin Forms 迁移到 NET MAUI 我们的应用程序几乎没有绘图功能 用户可以用手指进行绘图 我们用了TouchTrackingXamarin Forms 中的 nuget 包 但与 NET
  • 已发布的 .Net Core 应用程序警告安装 .Net Core,但它已安装

    我制作了一个 WPF 和控制台应用程序 供某人在我无法访问的私人服务器上使用 我使用 Visual Studio 2019 的内置 发布向导 来创建依赖于框架的单文件应用程序 当该人打开 WPF 应用程序时 他们会看到标准警告 他们单击 是
  • 在 C# 中为父窗体中的子窗体控件添加事件处理程序

    我有两种形式 一种是带有按钮和文本框的父表单 单击该按钮时 将打开一个对话框 该子窗体又包含一个文本框和一个按钮 现在我想要的是 每当子表单文本框中的文本更改时 父表单文本框中的文本会自动更改 为了获得这个 我所做的是 Form3 f3 n
  • 在 C 中使用枚举而不是 #defines 作为编译时常量是否合理?

    在 C 工作了一段时间后 我将回到 C 开发领域 我已经意识到 在不必要的时候应该避免使用宏 以便让编译器在编译时为您做更多的工作 因此 对于常量值 在 C 中我将使用静态 const 变量或 C 11 枚举类来实现良好的作用域 在 C 中
  • 将二变量 std::function 转换为单变量 std::function

    我有一个函数 它获取两个值 x 和 y 并返回结果 std function lt double double double gt mult double x double y return x y 现在我想得到一个常量 y 的单变量函数
  • 如何在 C# 中创建异步方法?

    我读过的每一篇博客文章都会告诉您如何在 C 中使用异步方法 但由于某些奇怪的原因 从未解释如何构建您自己的异步方法来使用 所以我现在有这段代码使用我的方法 private async void button1 Click object se
  • Visual Studio 2015 - Web 项目上缺少共享项目参考选项卡

    我从 MSDN 订阅升级到 Visual Studio 2015 因为我非常兴奋地阅读有关共享项目的信息 当我们想要做的只是重用代码时 不再需要在依赖项中管理 21382 个 nuget 包 所以我构建了一个测试共享项目 其中包含一些代码
  • 在 Win32 控制台应用程序中设置光标位置

    如何在 Win32 控制台应用程序中设置光标位置 最好 我想避免制作句柄并使用 Windows 控制台功能 我花了整个早上沿着那条黑暗的小巷跑 它产生的问题比它解决的问题还要多 我似乎记得当我在大学时使用 stdio 做这件事相对简单 但我
  • 为什么空循环使用如此多的处理器时间?

    如果我的代码中有一个空的 while 循环 例如 while true 它将把处理器的使用率提高到大约 25 但是 如果我执行以下操作 while true Sleep 1 它只会使用大约1 那么这是为什么呢 更新 感谢所有精彩的回复 但我
  • 如何在 C 中将 char 连接到 char* ?

    我怎样才能前置char c to char myChar 我有c值为 A and myChar值为 LL 我怎样才能前置c to myChar使 ALL 这应该有效 include

随机推荐

  • 按顺序拆分 Parallel.Foreach 循环上的负载

    我需要处理列表中的一百万个元素 将它们粗暴地扔进并行 ForEach只会让CPU饱和 相反 我将元素主列表分成几部分 并将子列表放入并行循环中 List
  • 我可以在 SSRS 中跨数据源“加入”吗?

    我有两个数据源 一个 Oracle 和一个 Sql Server 由于我之前的情况 就像我发现它时的情况一样 Oracle 数据库中的某些列包含来自 Sql Server 数据库中的查找表的 PK 我正在尝试创建一个 Sql Server
  • 如何在Notepad++中删除当前行并添加新行?

    如何在Notepad 中删除当前行并添加新行 这两个操作很常见 但我找不到任何关键设置如何在 Notepad 中执行它们 任何插件都可以完成这项工作吗 Ctrl L cuts the current line and Ctrl Shift
  • 我可以 gzip 压缩所有 html 内容(页面)吗

    我试图找出定义哪些页面应该进行 gzip 压缩以及何时发送纯 html 内容是否有任何原则 如果你们可以分享您在 gzip 压缩项目的一部分时所做的决定 那将会很有帮助 一个好主意是进行基准测试 对比数据下降的速度有多快 压缩得有多好 如果
  • MIPS:求 5 个整数的平均值

    客观的 根据用户输入 使用五个寄存器查找平均值 Example 1 3 2 9 4 Output 3 输出是 3 因为 3 8 是小数 我希望它是整数 我的目标是不使用数组 但我在添加所有 5 个寄存器时遇到问题 data prompt1
  • 多索引数据帧删除每组最大值的行

    我有一个像这样的多索引数据框 PID Fid x y A 1 2 3 2 6 1 3 4 6 B 1 3 5 2 2 4 3 5 7 我想删除每个患者 PID 具有最高 x 值的行 我需要获取一个包含剩余行和所有列的新数据框 以继续对这些数
  • 使用 Swift 将自定义“数字”图像添加到 SKLabelNode 作为 SpriteKit 中的分数

    我基本上想在 Singles 中添加自定义字体编号 带有图像 并使用 SpriteKit 在我的游戏中添加它们作为我的分数 这是字体图像样式 它们是从 0 到 9 的数字 一段时间以来我一直在试图解决这个问题 我不确定您是否可以将其添加到
  • 如何为 fllot 中的条形图赋予纯色

    我需要为条形图提供纯色 我已关注此链接条形图示例 http www saltycrane com blog 2010 03 jquery flot stacked bar chart example 但我想要提供纯色 而且我还需要自己改变颜
  • 如何获取第一次发生的事件,然后抑制事件 2 秒(RxJS)

    我认为 RxJS 应该完全适合抑制重复按钮点击 2 秒 然而 我在实施过程中遇到了困难 var button myButton button button toObservable click Throttle 2000 Wouldn t
  • 暂停和恢复 Android Repo 同步

    我正在尝试同步以下存储库 repo init u git github com SlimRoms platform manifest git b jb 问题是我大约 30 小时前就开始了仓库同步 但它仍然没有完成 我有 1Mbps 连接 我
  • 如何防止 Firefox 在按 ctrl 和 + 时放大?

    我正在尝试在 Firefox 中使用 ctrl 和 组合来为我们的 Web 应用程序执行不同的操作 当我们的 Web 应用程序正在侦听此事件时 如何防止 Firefox 缩放 我不想更改 Firefox 中的设置 但希望代码以某种方式执行此
  • Tkinter 中的按钮命令

    我正在尝试使用 tkinter 进行一次文本冒险 并且正在慢慢地将一些东西组合在一起 我试图显示从一个房间到另一个房间的命令 但即使按钮出现 当我按下它们时什么也没有发生 game py usr bin python coding utf
  • 在 Kibana 4 中向导航栏添加页面

    我正在尝试向 Kibana 4 添加欢迎 介绍页面 并且需要修改导航菜单 我在 src kibana plugins kibana kibana html 找到了导航源 html 文档 但无法弄清楚选项卡名称是从哪里注入的 这是进行调用的列
  • 使用 VS 11、.NET 4.5 和实体框架时生成错误

    在 Visual Studio 2010 中 我的解决方案使用 NET 4 2 实体框架 2011 年 6 月 CTP 因此我可以在实体框架中使用空间类型 当我升级到 Visual Studio 11 Beta 时 由于 4 2 和 4 5
  • 异常未传播到 Apache Camel 中的错误处理程序

    我有一条定义 doTry doCatch 块的路线 当在 doCatch 块中处理异常时 我希望将其传播到错误处理程序 以确保消息在本地处理后添加到死信队列中 问题是我无法让错误处理程序的传播正常工作 defaultErrorHandler
  • 将@interface放入.m文件中的逻辑是什么? [复制]

    这个问题在这里已经有答案了 可能的重复 h 和 m 文件中 interface 定义的区别 https stackoverflow com questions 3967187 difference between interface def
  • Android 5.0:如何更改最近使用的应用程序标题颜色?

    我正在使用 AppCompat 并且我的主题正在扩展Theme AppCompat Light DarkActionBar 当我在 Android 5 Lollipop 中按下最近使用的应用程序按钮时 我的应用程序会出现dark标题而不是
  • “DoCmd.OutputTo acOutputQuery”正在删除查询

    我遇到了一个问题DoCmd OutputTo acOutputQuery第二次运行时删除查询本身 这个错误有任何解决方法 补丁吗 至少对我来说似乎是一个错误 回复 你的评论 您是否进行了文件复制 或者是否在两个数据库之间复制了对象 如果是第
  • 64位linux内核如何从ELF启动32位进程

    通过查看binfmt elf c https elixir bootlin com linux v3 5 source fs binfmt elf c在内核源代码中 我无法弄清楚内核 64 位 在生成 32 位进程与 64 位进程时有何不同
  • 性能:boost.compute vs. opencl C++ 包装器

    以下代码分别使用 boost compute 和 opencl C 包装器将两个向量相加 结果显示 boost compute 几乎比 opencl c 包装器慢 20 倍 我想知道我是否错过了使用 boost compute 或者它确实很