oneAPI GPU 优化指南 - 移除条件检查

本文讨论了如何通过移除条件检查和使用关系函数(如min()和max())来优化SIMD向量计算性能,以提升共享本地内存(SLM)中的卷积操作效率。作者通过示例展示了在SYCL中如何实现这一优化过程。

本章节翻译by chenshusmail@163.com 原文:Removing Conditional Checks (intel.com)

目录

填充缓冲区以移除条件检查

用关系函数替换条件检查


在 子组(sub-group)和 SIMD 向量化 中, 我们了解到 SIMD 分歧会对性能产生负面影响。 如果 sub-group 中的所有 work-item 执行相同的指令,则 SIMD 通道得到最大程度的利用。 如果一个或多个 work-item 走了不同的路径,则两条路径都必须执行才能合并。

分歧是由条件检查引起的,尽管并非所有条件检查都会导致分歧。 一些条件检查,即使它们不会导致 SIMD 分歧,仍然可能是性能隐患。 总的来说,移除条件检查有助于提高性能。

填充缓冲区以移除条件检查

来看看 共享本地内存(SLM) 中的卷积示例:

    sycl::buffer<int> ibuf(input.data(), N);
    sycl::buffer<int> obuf(output.data(), N);
    sycl::buffer<int> kbuf(kernel.data(), M);

    auto e = q.submit([&](auto &h) {
      sycl::accessor iacc(ibuf, h, sycl::read_only);
      sycl::accessor oacc(obuf, h);
      sycl::accessor kacc(kbuf, h, sycl::read_only);

      h.parallel_for(sycl::nd_range<1>(sycl::range{N}, sycl::range{256}),
                     [=](sycl::nd_item<1> it) {
                       int i = it.get_global_linear_id();
                       int group = it.get_group()[0];
                       int gSize = it.get_local_range()[0];

                       int t = 0;
                       int _M = static_cast<int>(M);
                       int _N = static_cast<int>(N);

                       if ((group == 0) || (group == _N / gSize - 1)) {
                         if (i < _M / 2) {
                           for (int j = _M / 2 - i, k = 0; j < _M; ++j, ++k) {
                             t += iacc[k] * kacc[j];
                           }
                         } else {
                           if (i + _M / 2 >= _N) {
                             for (int j = 0, k = i - _M / 2;
                                  j < _M / 2 + _N - i; ++j, ++k) {
                               t += iacc[k] * kacc[j];
                             }
                           } else {
                             for (int j = 0, k = i - _M / 2; j < _M; ++j, ++k) {
                               t += iacc[k] * kacc[j];
                             }
                           }
                         }
                       } else {
                         for (int j = 0, k = i - _M / 2; j < _M; ++j, ++k) {
                           t += iacc[k] * kacc[j];
                         }
                       }

                       oacc[i] = t;
                     });
    });

嵌套的 if-then-else 条件检查是必要的,以检查输入中的第一个和最后一个 128 个元素, 这样索引就不会越界。如果我们在输入数组前后填充足够多的 0, 这些条件检查就可以被安全地移除:

  std::vector<int> input(N + M / 2 + M / 2);
  std::vector<int> output(N);
  std::vector<int> kernel(M);

  srand(2009);
  for (size_t i = M / 2; i < N + M / 2; ++i) {
    input[i] = rand();
  }

  for (size_t i = 0; i < M / 2; ++i) {
    input[i] = 0;
    input[i + N + M / 2] = 0;
  }

  for (size_t i = 0; i < M; ++i) {
    kernel[i] = rand();
  }

  {
    sycl::buffer<int> ibuf(input.data(), N + M / 2 + M / 2);
    sycl::buffer<int> obuf(output.data(), N);
    sycl::buffer<int> kbuf(kernel.data(), M);

    auto e = q.submit([&](auto &h) {
      sycl::accessor iacc(ibuf, h, sycl::read_only);
      sycl::accessor oacc(obuf, h);
      sycl::accessor kacc(kbuf, h, sycl::read_only);

      h.parallel_for(sycl::nd_range(sycl::range{N}, sycl::range{256}),
                     [=](sycl::nd_item<1> it) {
                       int i = it.get_global_linear_id();
                       int t = 0;

                       for (size_t j = 0; j < M; ++j) {
                         t += iacc[i + j] * kacc[j];
                       }

                       oacc[i] = t;
                     });
    });
    q.wait();

    size_t kernel_ns = (e.template get_profiling_info<
                            sycl::info::event_profiling::command_end>() -
                        e.template get_profiling_info<
                            sycl::info::event_profiling::command_start>());
    std::cout << "Kernel Execution Time Average: total = " << kernel_ns * 1e-6
              << " msec" << std::endl;
  }

用关系函数替换条件检查

另一种移除条件检查的方法是用关系函数替换它们,特别是内置关系函数。强烈建议使用内置函数(如果有)。 SYCL 提供了丰富的内置关系函数,如 select()min()max()。 在许多情况下,您可以使用这些函数替换条件检查并获得更好的性能。

再看看上边的卷积示例。if-then-else 条件检查可以用内置函数 min() and max() 来替换。

    sycl::buffer<int> ibuf(input.data(), N);
    sycl::buffer<int> obuf(output.data(), N);
    sycl::buffer<int> kbuf(kernel.data(), M);

    auto e = q.submit([&](auto &h) {
      sycl::accessor iacc(ibuf, h, sycl::read_only);
      sycl::accessor oacc(obuf, h);
      sycl::accessor kacc(kbuf, h, sycl::read_only);

      h.parallel_for(sycl::nd_range(sycl::range{N}, sycl::range{256}),
                     [=](sycl::nd_item<1> it) {
                       int i = it.get_global_linear_id();
                       int t = 0;
                       int startj = sycl::max<int>(M / 2 - i, 0);
                       int endj = sycl::min<int>(M / 2 + N - i, M);
                       int startk = sycl::max<int>(i - M / 2, 0);
                       for (int j = startj, k = startk; j < endj; j++, k++) {
                         t += iacc[k] * kacc[j];
                       }
                       oacc[i] = t;
                     });
    });

上一章                                         主目录    上级目录                                                               下一章

01、数据简介 出口韧性是地级市在面对外部震荡和压力时,能够承受并迅速适应、应对变化的能力。这种能力体现在地级市经济结构的灵活性、创新能力和竞争力,以及地方政府的政策支持和产业调整能力等多个方面。 城市出口韧性对于城市的经济发展、就业稳定、国际贸易地位以及风险抵御能力等方面都具有重要影响。因此,城市应加强出口韧性的建设,提高应对外部冲击的能力,以推动其经济的可持续发展。 数据名称:地级市-城市出口韧性数据 数据年份:2011-2022年 02、相关数据 代码 年份 地区 城市 省份 城市出口韧性 距离港口的最近距离 最终进口额_百万人民币2 最终出口额_百万人民币2 人均道路面积2 年末金融机构各项贷款余额万元2 地区生产总值万元2 科学支出万元2 地方财政一般预算内支出万元2 城镇居民人均可支配收入元2 固定资产投资2 实际使用外商投资额百万美元2 城镇化率2 外贸依存度 出口贸易 年平均汇率 实际使用外商投资额百万人民币2 外资依存度 金融发展水平 财政投资力度 科学技术水平 出口偏离度 x_地区生产总值万元2 x_城镇化率2 x_人均道路面积2 x_外贸依存度 x_出口贸易 x_出口偏离度 x_金融发展水平 x_城镇居民人均可支配收入元2 x_财政投资力度 x_科学技术水平 x_距离港口的最近距离 x_外资依存度 地区生产总值万元2_sum y_地区生产总值万元2 城镇化率2_sum y_城镇化率2 人均道路面积2_sum y_人均道路面积2 外贸依存度_sum y_外贸依存度 出口贸易_sum y_出口贸易 出口偏离度_sum y_出口偏离度 金融发展水平_sum y_金融发展水平 城镇居民人均可支配收入元2_sum y_城镇居民人均可支配收入元2 财政投资力度_sum y_财政投资力度 科学技术水平_sum y_科学技术水平
内容概要:本文档详细介绍了一个基于Matlab实现的无人机空中通信仿真资源包,系统涵盖了无人机通信、三维路径规划、状态估计与多机协同等多个核心技术模块的仿真代码与案例研究。内容聚焦于无人机在复杂环境下的三维路径规划(如基于遗传算法GA、粒子群算法PSO、动态窗口法DWA等)、无人机姿态与轨迹的状态估计算法(如扩展卡尔曼滤波器EKF、UKF、不变扩展卡尔曼滤波IEKF、粒子滤波PF等),以及无人机通信链路建模与优化,并融合智能优化算法对系统性能进行提升。此外,资源包还拓展至微电网优化、MIMO检测、图像融合、信号处理等相关科研领域,构建了一个以无人机技术为核心、多学科交叉融合的综合性仿真研究体系。; 适合人群:具备一定Matlab编程能力与控制系统基础知识,从事无人机系统设计、无线通信、自动化控制、智能优化算法或相关领域研究的科研人员、高校研究生及工程技术人员。; 使用场景及目标:①开展无人机通信系统建模与性能仿真分析;②实现复杂动态环境中无人机三维路径规划与实时避障;③研究基于多源传感器融合的无人机导航与状态估计方法;④结合智能优化算法提升无人机任务执行效率与系统鲁棒性; 阅读建议:建议读者依据资源包提供的模块化结构系统学习,优先掌握Matlab/Simulink基本仿真技能,重点研读路径规划与状态估计部分的算法实现与代码细节,并通过实际调试与二次开发加深对无人机系统集成与优化策略的理解。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值