SSE 双线性插值

2024-02-26

我正在紧密循环中实现双线性插值,并尝试使用 SSE 对其进行优化,但我从中得到的加速为零。

这是代码,非 SIMD 版本使用简单的向量结构,可以定义为struct Vec3f { float x, y, z; }实现乘法和加法运算符:

#ifdef USE_SIMD
    const Color c11 = pixelCache[y1 * size.x + x1];
    const Color c12 = pixelCache[y2 * size.x + x1];
    const Color c22 = pixelCache[y2 * size.x + x2];
    const Color c21 = pixelCache[y1 * size.x + x2];

    __declspec(align(16)) float mc11[4] = { 1.0, c11.GetB(), c11.GetG(), c11.GetR() };
    __declspec(align(16)) float mc12[4] = { 1.0, c12.GetB(), c12.GetG(), c12.GetR() };
    __declspec(align(16)) float mc22[4] = { 1.0, c22.GetB(), c22.GetG(), c22.GetR() };
    __declspec(align(16)) float mc21[4] = { 1.0, c21.GetB(), c21.GetG(), c21.GetR() };

    // scalars in vector form for SSE
    const float s11 = (x2-x)*(y2-y);
    const float s12 = (x2-x)*(y-y1);
    const float s22 = (x-x1)*(y-y1);
    const float s21 = (x-x1)*(y2-y);

    __declspec(align(16)) float ms11[4] = {1.0, s11, s11, s11};
    __declspec(align(16)) float ms12[4] = {1.0, s12, s12, s12};
    __declspec(align(16)) float ms22[4] = {1.0, s22, s22, s22};
    __declspec(align(16)) float ms21[4] = {1.0, s21, s21, s21};

    __asm {
        movaps xmm0, mc11
        movaps xmm1, mc12
        movaps xmm2, mc22
        movaps xmm3, mc21

        movaps xmm4, ms11
        movaps xmm5, ms12
        movaps xmm6, ms22
        movaps xmm7, ms21

        mulps xmm0, xmm4
        mulps xmm1, xmm5
        mulps xmm2, xmm6
        mulps xmm3, xmm7

        addps xmm0, xmm1
        addps xmm0, xmm2
        addps xmm0, xmm3

        movaps mc11, xmm0
    }
#else
    const Vec3f c11 = toFloat(pixelCache[y1 * size.x + x1]);
    const Vec3f c12 = toFloat(pixelCache[y2 * size.x + x1]);
    const Vec3f c22 = toFloat(pixelCache[y2 * size.x + x2]);
    const Vec3f c21 = toFloat(pixelCache[y1 * size.x + x2]);

    const Vec3f colour =
            c11*(x2-x)*(y2-y) +
            c21*(x-x1)*(y2-y) +
            c12*(x2-x)*(y-y1) +
            c22*(x-x1)*(y-y1);
#endif

重新排列 asm 代码以重用寄存器(最终只有三个 xmm 寄存器)没有产生任何效果。我也尝试过使用内在函数:

// perform bilinear interpolation
const Vec3f c11 = toFloat(pixelCache[y1 * size.x + x1]);
const Vec3f c12 = toFloat(pixelCache[y2 * size.x + x1]);
const Vec3f c22 = toFloat(pixelCache[y2 * size.x + x2]);
const Vec3f c21 = toFloat(pixelCache[y1 * size.x + x2]);

// scalars in vector form for SSE
const float s11 = (x2-x)*(y2-y);
const float s12 = (x2-x)*(y-y1);
const float s22 = (x-x1)*(y-y1);
const float s21 = (x-x1)*(y2-y);

__m128 mc11 = _mm_set_ps(1.f, c11.b, c11.g, c11.r);
__m128 mc12 = _mm_set_ps(1.f, c12.b, c12.g, c12.r);
__m128 mc22 = _mm_set_ps(1.f, c22.b, c22.g, c22.r);
__m128 mc21 = _mm_set_ps(1.f, c21.b, c21.g, c21.r);

__m128 ms11 = _mm_set_ps(1.f, s11, s11, s11);
__m128 ms12 = _mm_set_ps(1.f, s12, s12, s12);
__m128 ms22 = _mm_set_ps(1.f, s22, s22, s22);
__m128 ms21 = _mm_set_ps(1.f, s21, s21, s21);

mc11 = _mm_mul_ps(mc11, ms11);
mc12 = _mm_mul_ps(mc12, ms12);
mc22 = _mm_mul_ps(mc22, ms22);
mc21 = _mm_mul_ps(mc21, ms21);

mc11 = _mm_add_ps(mc11, mc12);
mc11 = _mm_add_ps(mc11, mc22);
mc11 = _mm_add_ps(mc11, mc21);

Vec3f colour;
_mm_storeu_ps(colour.array, mc11);

但无济于事。我错过了什么,还是不可能在这里获得任何额外的速度?


为什么要浮点数? 给定 a、b、c、d 和 xerr、yerr 在 0-256 范围内的压缩像素 argb,一个简单的示例是:

// =================================================================================================================
// xs_Bilerp
// =================================================================================================================
finline uint32 xs_Bilerp (uint32 a, uint32 b, uint32 c, uint32 d, uint32 xerr, uint32 yerr)
{
    #define xs_rbmask    0x00ff00ff
    #define xs_agmask    0xff00ff00

    if (a==b && c==d && a==d)   return a;

    const uint32 arb        =   a & xs_rbmask;
    const uint32 crb        =   c & xs_rbmask;
    const uint32 aag        =   a & xs_agmask;
    const uint32 cag        =   c & xs_agmask;

    const uint32 rbdx1      =  (b & xs_rbmask) - arb;
    const uint32 rbdx2      =  (d & xs_rbmask) - crb;
    const uint32 agdx1      = ((b & xs_agmask)>>8) - (aag >> 8);
    const uint32 agdx2      = ((d & xs_agmask)>>8) - (cag >> 8);

    const uint32 rb1        = (arb      + ((rbdx1 * xerr) >> 8)) & xs_rbmask;
    const uint32 ag1        = (aag      + ((agdx1 * xerr)     )) & xs_agmask;
    const uint32 rbdy       = ((crb     + ((rbdx2 * xerr) >> 8)) & xs_rbmask)       - rb1;
    const uint32 agdy       = (((cag    + ((agdx2 * xerr)     )) & xs_agmask)>>8)   - (ag1 >> 8);

    const uint32 rb         = (rb1 + ((rbdy * yerr) >> 8)) & xs_rbmask;
    const uint32 ag         = (ag1 + ((agdy * yerr)     )) & xs_agmask;

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

SSE 双线性插值 的相关文章

随机推荐

  • 在 Android WebView 中启用 WebGL

    如何在 Android 5 1 1 模拟器的 WebView 小部件中启用 WebGL 我通过检查了 WebGL 状态Webgl 报告 http webglreport com结果是 此浏览器支持 WebGL 但它被禁用或不可用 有时这是由
  • JTable + TableModel 缓存获取事件以进行延迟实例化?

    设想 您正在使用带有自定义 TableModel 的 JTable 来查看位于数据库或网络或其他位置的某些集合的内容 完成这项工作的强力方法是立即加载整个集合 假设由于所需资源的原因 这是不切实际的 解决该问题的简单方法是在 JTable
  • AWS Cognito-删除登录页面中的注册

    我正在使用 Aws Cognito 但无法找到从 Cognito 登录页面删除注册按钮的解决方案 谢谢 Cognito 用户池提供了默认登录页面 其中包含忘记密码 登录和注册 但我想从该页面隐藏 删除注册 在 AWS 管理控制台中 转到 C
  • 使用 Flying Saucer 将 xhtml 字符串转换为 PDF 的最简单方法是什么?

    我一直在使用飞碟 http code google com p flying saucer 一段时间以来 取得了令人惊叹的成果 我可以像这样通过 uri 设置文档 ITextRenderer renderer new ITextRender
  • django-allauth 未捕获的引用错误

    我无法弄清楚为什么我会得到 未捕获的引用错误 allauth 未定义 点击 Facebook 链接时 https obscure harbor 7751 herokuapp com accounts signup https obscure
  • 如何与核心数据创建多对多关系?斯威夫特,Xcode

    我有 2 个实体 实体 1 人 实体2 书籍 人们实体有一个属性 它是他们最喜欢的书籍的字符串名称数组 我需要创建一种关系 以某种方式将一个人最喜欢的书映射到相应的书籍实体对象 我不知道该怎么做 到目前为止 我首先通过将目的地设置为 书籍
  • 有没有办法在第一次失败后停止 DataAnnotation 验证?

    在我的 ViewModel 中 我使用多个 DataAnnotation 来验证表单数据 每个字段通常有 2 3 个注释 例如 电子邮件地址字段可能如下所示 Required ErrorMessage Please enter an ema
  • 您应该将 SQL 存储过程存储在源代码管理中吗?

    当开发包含大量存储过程的应用程序时 是否应该将它们存储在某种源版本控制系统 例如源安全 TFS SVN 中 如果是这样 为什么 是否有一种方便的前端方法可以使用 SQL Server Management Studio 来执行此操作 是的
  • 为什么 Django REST Framework 中的 SessionAuthentication 永远不会返回 HTTP401

    看着the docs http www django rest framework org api guide authentication sessionauthentication and 来源 https github com tom
  • 蟒蛇 | mktime溢出错误

    我已经在网上搜索过 但找不到针对此问题的合适解决方案 OverflowError mktime argument out of range 导致该异常的代码 t 1956 3 2 0 0 0 0 0 0 ser time mktime t
  • IE 是唯一不允许 Flash 对象操作的浏览器(或版本)吗?

    我已经尝试了多种方法通过 Javascript 编辑 Flash 对象 嵌入 它似乎适用于除 IE 之外的所有浏览器 因此我正在考虑将 IE 扔出此应用程序的窗口 除非有较旧的 使用过的其他浏览器版本也不允许您编辑对象 一个例子是 docu
  • ASP.NET MVC,“需要票证”属性

    我正在尝试构建一个允许用户执行某些操作的系统 但他们的帐户每次执行操作时都必须有一个特定的 票证 例如 假设他们希望创建一个Product 他们需要一个CreateProductTicket 当然 我可以简单地使用一些 if 语句来做到这一
  • jQuery 验证 - 两个字段,只需填写一个

    我正在使用jQuery 验证插件 http bassistance de jquery plugins jquery plugin validation 在我的表格上 我的表格上有一个 电话 字段和一个 手机号码 场地 我该如何制作 以便用
  • 在 SVG 路径中填充形状/图标 (js)

    我有一个带有路径的 SVG
  • 带有交叉验证的 scikits 混淆矩阵

    我正在使用 scikits 接口通过交叉验证 stratifiedKfold 训练 svm 分类器 对于每个测试集 k 个 我都会得到一个分类结果 我想要一个包含所有结果的混淆矩阵 Scikits 有一个混淆矩阵接口 sklearn met
  • 意外的tornado.ioloop.PeriodicCallback行为

    试图弄清楚如何PeriodicCallback已经安排好了 我写了这个脚本 import time import tornado ioloop t0 time time def foo time sleep 1 print time tim
  • 在 jenkins docker 容器内执行 docker host 命令

    我有一个运行 jenkins 的 docker 容器 我想在这个容器内部启动其他容器 所以在这个容器外部 我尝试用以下命令启动我的詹金斯控制器 docker run v var run docker sock var run docker
  • 如何缩小 Ruby 源文件?

    我有一种情况 我希望能够minify 未编译 Ruby 脚本 目标是 减少脚本的整体字符数 执行一定程度的混淆 使其他人难以修改代码 我们可以假设 是的 我知道我在做什么 而且我确实想缩小和混淆代码 Ruby 源代码具有简单的语法 并且不使
  • 列出 Google Drive 中所有文件的脚本:Api、cURL 和 Bash

    这是一个 bash 脚本 使用 cURL 列出我的 Google Drive 帐户 不是与我分享文件 只有我自己的文件 您必须在您的帐户中授予对 Google Drive API 的访问权限 并在脚本中填充变量 idclient and i
  • SSE 双线性插值

    我正在紧密循环中实现双线性插值 并尝试使用 SSE 对其进行优化 但我从中得到的加速为零 这是代码 非 SIMD 版本使用简单的向量结构 可以定义为struct Vec3f float x y z 实现乘法和加法运算符 ifdef USE