优化 2D 旋转

2024-02-05

给出在 2D 空间中旋转点的经典公式:

cv::Point pt[NPOINTS];
cv::Point rotated[NPOINTS];
float angle = WHATEVER;
float cosine = cos(angle);
float sine = sin(angle);

for (int i = 0; i < NPOINTS; i++)
{
    rotated[i].x = pt[i].x * cosine - pt[i].y * sine;
    rotated[i].y = pt[i].x * sine   + pt[i].y * cosine;
}

假设 NPOINTS 是 32 并且数组是对齐的,那么如何优化 SSE 或 AVX 的代码呢?在这里和其他地方搜索没有发现任何有用的东西,我在这里迷路了:

__m128i onePoint = _mm_set_epi32(pt[i].x, pt[i].y, pt[i].x, pt[i].y);
__m128 onefPoint = _m128_cvtepi32_ps(onePoint);
__m128 sinCos = _mm_set_ps(cosine, -sine, sine, cosine);
__m128 rotated = _mm_mul_ps(onefPoint, sinCos);

但如何从[y*cosine, -x*sine, x*sine, y*cosine] to [y*cosine + -x*sine, x*sine + y*cosine]?这是最好的方法吗?它是否可以轻松扩展到__m512?

UPDATE:我做了更多研究,现在大约有:

__m128i onePoint = _mm_set_epi32(pt[i].x, pt[i].y, pt[i].x, pt[i].y);
__m128 onefPoint = _m128_cvtepi32_ps(onePoint);
__m128i twoPoint = _mm_set_epi32(pt[i+1].x, pt[i+1].y, pt[i+1].x, pt[i+1].y);
__m128 twofPoint = _m128_cvtepi32_ps(twoPoint);
__m128 sinCos = _mm_set_ps(cosine, -sine, sine, cosine);
__m128 rotated1 = _mm_mul_ps(onefPoint, sinCos);
__m128 rotated2 = _mm_mul_ps(twofPoint, sinCos);
__m128 added = _mm_hadd_ps(rotated1, rotated2);
__m128i intResult = _mm_cvtps_epi32(added);
int results[4];
_mm_storeu_si128((__m128i*)results, intResult);

这使得处理器时间提高了 50%,从 11% 提高到约 6%。扩展到__m256一次做四个点可以进一步提高速度。这看起来很糟糕的代码,但我的方向正确吗?


使用数组结构数组 (AoSoA) 并一次处理八个点。在下面的代码中point8是包含八个点的数组结构。功能rotate_point8旋转八个点并与函数具有相同的代数结构rotate_point旋转单个点。功能rotate_all8使用 AoSoA 旋转 32 点point8*.

单点旋转代码执行 4 次乘法、1 次加法和 1 次减法。

如果我们看一下大会为rotate_point8 https://godbolt.org/g/EYXNN5我们看到 GCC 展开循环并在每次展开时执行 4 次 SIMD 乘法、1 次 SIMD 加法和 1 次 SIMD 减法。这是你能做的最好的事情:用一件的价格买八件。

#include <x86intrin.h>
#include <stdio.h>
#include <math.h>

struct point8 {
  __m256 x;
  __m256 y;
};

struct point {
  float x;
  float y;
};

static point rotate_point(point p, float a, float b) {
  point r;
  r.x = p.x*a - p.y*b;
  r.y = p.x*b + p.y*a;
  return r;
}

static point8 rotate_point8(point8 p, float a, float b) {
  __m256 va = _mm256_set1_ps(a), vb = _mm256_set1_ps(b);
  point8 r;
  r.x = _mm256_sub_ps(_mm256_mul_ps(p.x,va), _mm256_mul_ps(p.y,vb));
  r.y = _mm256_add_ps(_mm256_mul_ps(p.x,vb), _mm256_mul_ps(p.y,va));
  return r;
}

void rotate_all(point* points, point* r, float angle) {
  float a = cos(angle), b = sin(angle);
  for(int i=0; i<32; i++) r[i] = rotate_point(points[i], a, b);
}

void rotate_all8(point8* points, point8* r8, float angle) {
  float a = cos(angle), b = sin(angle);
  for(int i=0; i<4; i++) r8[i] = rotate_point8(points[i], a, b);
}

int main(void) {
  float x[32], y[32];
  point p[32], r[32];
  point8 p8[4], r8[4];
  float angle = 3.14159f/4;

  for(int i=0; i<32; i++) y[i] = 1.0*i/31, x[i] = sqrt(1-y[i]*y[i]);
  for(int i=0; i<32; i++) p[i].x = x[i], p[i].y = y[i];
  for(int i=0; i<4; i++) p8[i].x = _mm256_load_ps(&x[8*i]), p8[i].y = _mm256_load_ps(&y[8*i]); 

  for(int i=0; i<32; i++) printf("%f %f\n", p[i].x, p[i].y); puts("");

  rotate_all(p, r, angle);
  for(int i=0; i<32; i++) printf("%f %f\n", r[i].x, r[i].y); puts("");

  rotate_all8(p8, r8, angle);
  for(int i=0; i<4; i++) {
    _mm256_storeu_ps(x, r8[i].x), _mm256_storeu_ps(y, r8[i].y);
    for(int j=0; j<8; j++) printf("%f %f\n", x[j], y[j]);
  }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

优化 2D 旋转 的相关文章

  • 未提供参数时如何指定 C# System.Commandline 行为?

    在我的控制台应用程序中 当未提供控制台参数时 将执行我指定列表 在本例中为参数 3 的任何处理程序 调用该处理程序时 布尔参数设置为 false 但对我来说 根本不调用它更有意义 如何防止这种情况发生并显示帮助文本 using System
  • 如何在 .NET Framework 2.0 中模拟“Func<(Of <(TResult>)>) 委托”?

    我尝试使用这个类代码项目文章 http www codeproject com KB threads AsyncVar aspx在 VB NET 和 NET Framework 2 0 中 除了这一行之外 所有内容似乎都可以编译Privat
  • 确保 StreamReader 不会挂起等待数据

    下面的代码读取从 tcp 客户端流读取的所有内容 并且在下一次迭代中它将仅位于 Read 上 我假设正在等待数据 我如何确保它不会在没有任何内容可供读取时返回 我是否必须设置低超时 并在失败时响应异常 或者有更好的办法吗 TcpClient
  • 如何创建包含 IPv4 地址的文本框? [复制]

    这个问题在这里已经有答案了 如何制作一个这样的文本框 我想所有的用户都见过这个并且知道它的功能 您可以使用带有 Mask 的 MaskedTestBox000 000 000 000 欲了解更多信息 请参阅文档 http msdn micr
  • 回发后刷新时提示确认表单重新提交。我做错了什么?

    我有一个以空白 默认状态启动的仪表板 我让用户能够将保存的状态加载到仪表板中 当他们单击 应用 按钮时 我运行以下代码 function CloseAndSave var radUpload find radUpload1ID var in
  • 在 Visual Studio 2010 中从 Fortran 调用 C++ 函数

    我想从 Fortran 调用 C 函数 为此 我在 Visual Studio 2010 中创建了一个 FORTRAN 项目 之后 我将一个 Cpp 项目添加到该 FORTRAN 项目中 当我要构建程序时出现以下错误 Error 1 unr
  • 为什么调用非 const 成员函数而不是 const 成员函数?

    为了我的目的 我尝试包装一些类似于 Qt 共享数据指针的东西 经过测试 我发现当应该调用 const 函数时 会选择它的非 const 版本 我正在使用 C 0x 选项进行编译 这是一个最小的代码 struct Data int x con
  • 具有交替类型的可变参数模板参数包

    我想知道是否可以使用参数包捕获交替参数模式 例如 template
  • 我可以使用 moq Mock 来模拟类而不是接口吗?

    正在经历https github com Moq moq4 wiki Quickstart https github com Moq moq4 wiki Quickstart 我看到它 Mock 一个接口 我的遗留代码中有一个没有接口的类
  • DbContext 和 ObjectContext 有什么区别

    From MSDN 表示工作单元和存储库模式的组合 使您能够查询数据库并将更改分组在一起 然后将这些更改作为一个单元写回存储 DbContext在概念上类似于ObjectContext 我虽然DbContext只处理与数据库的连接以及针对数
  • Opencv Java 灰度

    我编写了以下程序 尝试从彩色转换为灰度 Mat newImage Imgcodecs imread q1 jpg Mat image new Mat new Size newImage cols newImage rows CvType C
  • 使用自定义堆的类似 malloc 的函数

    如果我希望使用自定义预分配堆构造类似 malloc 的功能 那么 C 中最好的方法是什么 我的具体问题是 我有一个可映射 类似内存 的设备 已将其放入我的地址空间中 但我需要获得一种更灵活的方式来使用该内存来存储将随着时间的推移分配和释放的
  • C#:帮助理解 UML 类图中的 <>

    我目前正在做一个项目 我们必须从 UML 图编写代码 我了解 UML 类图的剖析 但我无法理解什么 lt
  • 外键与独立关系 - Entity Framework 5 有改进吗?

    我读过了several http www ladislavmrnka com 2011 05 foreign key vs independent associations in ef 4 文章和问题 https stackoverflow
  • AES 128 CBC 蒙特卡罗测试

    我正在 AES 128 CBC 上执行 MCT 如中所述http csrc nist gov groups STM cavp documents aes AESAVS pdf http csrc nist gov groups STM ca
  • 按 Esc 按键关闭 Ajax Modal 弹出窗口

    我已经使用 Ajax 显示了一个面板弹出窗口 我要做的是当用户按 Esc 键时关闭该窗口 这可能吗 如果有人知道这一点或以前做过这一点 请帮助我 Thanks 通过以下链接 您可以通过按退出按钮轻松关闭窗口 http www codepro
  • 方法优化 - C#

    我开发了一种方法 允许我通过参数传入表 字符串 列数组 字符串 和值数组 对象 然后使用这些参数创建参数化查询 虽然它工作得很好 但代码的长度以及多个 for 循环散发出一种代码味道 特别是我觉得我用来在列和值之间插入逗号的方法可以用不同的
  • 无法接收 UDP Windows RT

    我正在为 Windows 8 RT 编写一个 Windows Store Metro Modern RT 应用程序 需要在端口 49030 上接收 UDP 数据包 但我似乎无法接收任何数据包 我已按照使用教程进行操作DatagramSock
  • WebSocket安全连接自签名证书

    目标是一个与用户电脑上安装的 C 应用程序交换信息的 Web 应用程序 客户端应用程序是 websocket 服务器 浏览器是 websocket 客户端 最后 用户浏览器中的 websocket 客户端通过 Angular 持久创建 并且
  • 我的班级应该订阅自己的公共活动吗?

    我正在使用 C 3 0 遵循标准事件模式我有 public event EventHandler

随机推荐

  • 将字节数组转换为 POD

    比方说 我有一个无符号字符数组 代表一堆 POD 对象 例如 从套接字或通过 mmap 读取 它们代表哪些类型以及在什么位置是在运行时确定的 但我们假设每个类型都已经正确对齐 将这些字节 转换 为相应 POD 类型的最佳方法是什么 解决方案
  • SQL/C# - 执行查询的最佳方法

    我需要从 C 类中执行 sql 查询 我想到了2个选择 启动sqlcmd进程 使用 SqlCommand 对象 我的问题是哪种方法更好 重要的是 该解决方案只能在短时间内保持与服务器的连接 如果上述想法不好 我愿意接受其他想法 提前致谢 使
  • select 的 Angular ng-change 不调用声明的方法

    我有以下 html 表单选择语句
  • 将 C# MethodInvoker.Invoke() 用于 GUI 应用程序...这样好吗?

    使用 C 2 0 和 MethodInvoker 委托 我有一个 GUI 应用程序从 GUI 线程或工作线程接收一些事件 我使用以下模式来处理表单中的事件 private void SomeEventHandler object sende
  • 错误:Angular2 中没有 HttpHandler 的提供者

    我正在尝试通过拦截器实现 HttpCache 以下是caching interceptor service ts import HttpRequest HttpResponse HttpInterceptor HttpHandler Htt
  • Linux 中的 Eclipse Luna UI 渲染

    我在 Fedora 19 中安装了 Eclipse Luna 并面临以下问题 与 Windows 安装相比 选项卡标题似乎很大 我在主目录中搜索并编辑了 gtkrc 2 0 文件 这使得选项卡更小 但我使用高对比度外观而不是 GTK 来获得
  • 提交时显示“您的二进制文件未针对 iPhone 5 进行优化”(ITMS-90096)

    这是我的第一个 iOS 应用程序 当我尝试将其提交到应用程序商店时 它给了我 ITMS 90096 错误 我想我已经上传了所有正确的图标和启动画面图像 它提到了 iphone 5 上 4 英寸显示屏的启动图像 但我不知道在哪里添加它 这是我
  • 如何将 Base64 字符串保存到文件并使用 Flutter 查看它

    我需要使用 Flutter 下载并查看文件 如果可能的话 图像 PDF 等 我的问题是 我要下载的文件是 Base64 String 我如何使用 Flutter 来实现这一点 以下是解码 Base64 字符串并将其保存为本地设备上的文件的代
  • Xcode 6 - 如何为 Ad-Hoc 分发选择签名证书/配置文件?

    为了将应用程序分发给我们的测试人员 我们使用 Xcode 我们使用以下过程来执行此操作 归档申请 临时分发 选择配置文件 将 ipa 保存到文件夹 但与Xcode 6 这个工作流程发生了一些变化 我仍然可以选择 Ad Hoc 分发选项 但无
  • 在chrome中将html保存为pdf

    我在用rmarkdown生成 HTML 报告 我在受限制的机器上 无法安装 tex 所以 我试图生成一个 HTML 文档 然后将其转换 打印为 pdf 示例 Markdown 文档是 title trials author Foo Bar
  • ubuntu 上的 Rscript

    我可以从哪里安装 Rscript 我需要使用 exec 从 php 文件运行 R 脚本 不过我需要先安装 Rscript R 的主包称为r base https packages ubuntu com search keywords r b
  • CSS/HTML:如何在全页 JS 上自定义箭头?

    我正在使用全页 JShttps github com alvarotrigo fullPage js https github com alvarotrigo fullPage js 制作我的网站 但是 当尝试更改箭头样式时 control
  • 使用 SQL 查询根据值复制和拆分行?

    我有一组数据 想要根据列值拆分多行 例如 源数据 预期输出 谢谢 劳伦斯A 解决上述问题的最佳且简单的方法是 SELECT value AS UID NAME Age Education Department FROM StackSoln
  • 将 TabControl 绑定到枚举

    我需要将所有枚举值显示为 TabControl 上的选项卡项 除了一个枚举成员 无 enum MyEnum Value1 Value2 Value3 None TabControl 应显示三个选项卡 Value1 Value2 和 Valu
  • auth.views.Loginview 显示“__init__() 收到意外的关键字参数‘请求’”

    我正在尝试使用内置的 djangosLoginView 但显示错误 init got an unexpected keyword argument request 批处理簿 用户 urls py from django urls impor
  • 如何在R中设置C堆栈的大小?

    我正在尝试使用spread 函数从tidyr在 R 中将其封装在一个包含大约 300 万个观测值的数据帧上 它返回以下错误消息 Error C stack usage 26498106 is too close to the limit 当
  • Spring 3 项目上的 java.lang.ClassNotFoundException:org.codehaus.jackson.map.ObjectMapper

    我正在尝试在没有 Maven 的情况下建立一个 Spring 项目 我的项目必须通过 Spring MVC 框架提供 jsp 页面和 json 流 Jsp 页面的部分运行良好 但是当我尝试设置 json 流 为了进行 ajax GET 时
  • Java 中 JSON 注入的 Fortify 错误

    我正进入 状态SUBSCRIPTION JSON来自客户端 我将其转换为字符串 然后使用 gson 库将其设置为模型对象 在 Fortify security 上运行代码时 下面的代码出现 Json 注入错误 并显示以下消息 这是错误 On
  • 请求太大

    我的页面上收到以下错误 我更新了 IIS 设置以进行发布限制 但找不到如何增加工作缓冲区大小 对此的任何帮助都很棒 Request Too Large The POST request is too large for the intern
  • 优化 2D 旋转

    给出在 2D 空间中旋转点的经典公式 cv Point pt NPOINTS cv Point rotated NPOINTS float angle WHATEVER float cosine cos angle float sine s