适用于 AVX 和 SSE 的 Visual Studio 的 cpu 调度程序

2024-05-06

我使用两台计算机工作。一种不支持 AVX,另一种支持 AVX。让我的代码在运行时找到我的CPU支持的指令集并选择合适的代码路径会很方便。 我按照 Agner Fog 的建议制作了一个 CPU 调度程序(http://www.agner.org/optimize/#vectorclass http://www.agner.org/optimize/#vectorclass)。然而,在我的机器上,如果没有 AVX 编译并与 Visual Studio 链接,启用 AVX 的代码会导致代码在运行时崩溃。

我的意思是,例如,我有两个源文件,一个源文件使用一些 SSE2 指令定义了 SSE2 指令集,另一个源文件定义了 AVX 指令集并使用一些 AVX 指令。在我的主函数中,如果我只引用 SSE2 函数,由于任何启用了 AVX 且带有 AVX 指令的源代码,代码仍然会崩溃。有什么线索可以告诉我如何解决这个问题吗?

编辑: 好吧,我想我已经隔离了问题。我正在使用 Agner Fog 的矢量类,并且我已将三个源文件定义为:

//file sse2.cpp - compiled with /arch:SSE2
#include "vectorclass.h"
float func_sse2(const float* a) {
    Vec8f v1 = Vec8f().load(a);
    float sum = horizontal_add(v1);
    return sum;
}
//file avx.cpp - compiled with /arch:AVX
#include "vectorclass.h"
float func_avx(const float* a) {
    Vec8f v1 = Vec8f().load(a);
    float sum = horizontal_add(v1);
    return sum;
}
//file foo.cpp - compiled with /arch:SSE2
#include <stdio.h>
extern float func_sse2(const float* a);
extern float func_avx(const float* a);
int main() {
    float (*fp)(const float*a); 
    float a[] = {1,2,3,4,5,6,7,8};
    int iset = 6;
    if(iset>=7) { 
        fp = func_avx;  
    }
    else { 
        fp = func_sse2;
    }
    float sum = (*fp)(a);
    printf("sum %f\n", sum);
}

这会崩溃。如果我在 func_SSE2 中使用 Vec4f 它不会崩溃。我不明白这一点。只要我没有带有 AVX 的其他源文件,我就可以将 Vec8f 与 SSE2 一起使用。阿格纳·福格的手册说

“使用 256 位浮点向量类(Vec8f、 Vec4d)除非指定AVX指令集,但是可以方便使用 无论如何,无论是否使用 AVX 使用相同的源代码,这些类都是如此。 每个 256 位向量在编译时将简单地分为两个 128 位向量 没有 AVX。”

然而,当我有两个带有 Vec8f 的源文件时,一个是用 SSE2 编译的,另一个是用 AVX 编译的,然后我就崩溃了。

编辑2: 我可以从命令行让它工作

>cl -c sse2.cpp
>cl -c /arch:AVX avx.cpp
>cl foo.cpp sse2.obj avx.obj
>foo.exe

编辑3: 然而,这会崩溃

>cl -c sse2.cpp
>cl -c /arch:AVX avx.cpp
>cl foo.cpp avx.obj sse2.obj
>foo.exe

另一个线索。显然,链接的顺序很重要。如果 avx.obj 在 sse2.obj 之前,它会崩溃,但如果 sse2.obj 在 avx.obj 之前,它不会崩溃。我不确定它是否选择了正确的代码路径(我现在无法访问我的 AVX 系统),但至少它不会崩溃。


我意识到这是一个老问题,而且问这个问题的人似乎已经不在了,但我昨天遇到了同样的问题。这是我的成果。

编译时,sse2.cpp 和 avx.cpp 文件都会生成目标文件,其中不仅包含您的函数,还包含任何所需的模板函数。 (例如。Vec8f::load)这些模板函数也是使用请求的指令集编译的。

这意味着您的 sse2.obj 和 avx.obj 目标文件都将包含以下定义Vec8f::load每个都使用各自的指令集进行编译。

然而,由于编译器处理Vec8f::load作为外部可见,它将其放置在目标文件的“COMDAT”部分,并带有“selectany”(又名“pick any”)标签。这告诉链接器,如果它看到这个符号的多个定义,例如在两个不同的目标文件中,那么它就可以选择它喜欢的任何一个。 (这样做是为了减少最终可执行文件中的重复代码,否则这些代码的大小会因模板和内联函数的多个定义而膨胀。)

您遇到的问题与此直接相关,因为传递给链接器的目标文件的顺序会影响它选择哪个文件。具体来说,它似乎正在选择它看到的第一个定义。

如果这是 avx.obj 那么 AVX 编译版本Vec8F::load会一直被使用。这将在不支持该指令集的机器上崩溃。 另一方面,如果 sse2.obj 位于第一个,则将始终使用 SSE2 编译版本。这不会崩溃,但即使支持 AVX,它也只会使用 SSE2 指令。

如果您查看链接器“map”文件输出(使用 /map 选项生成),就可以看出这种情况。以下是相关的(编辑过的)摘录 -

//
// link with sse2.obj before avx.obj
//
0001:00000080  _main                             foo.obj
0001:00000330  func_sse2@@YAMPBM@Z               sse2.obj
0001:00000420  ??0Vec256fe@@QAE@XZ               sse2.obj
0001:00000440  ??0Vec4f@@QAE@ABT__m128@@@Z       sse2.obj
0001:00000470  ??0Vec8f@@QAE@XZ                  sse2.obj <-- sse2 version used
0001:00000490  ??BVec4f@@QBE?AT__m128@@XZ        sse2.obj
0001:000004c0  ?get_high@Vec8f@@QBE?AVVec4f@@XZ  sse2.obj
0001:000004f0  ?get_low@Vec8f@@QBE?AVVec4f@@XZ   sse2.obj
0001:00000520  ?load@Vec8f@@QAEAAV1@PBM@Z        sse2.obj <-- sse2 version used
0001:00000680  ?func_avx@@YAMPBM@Z               avx.obj
0001:00000740  ??BVec8f@@QBE?AT__m256@@XZ        avx.obj

//
// link with avx.obj before sse2.obj
//
0001:00000080  _main                             foo.obj
0001:00000270  ?func_avx@@YAMPBM@Z               avx.obj
0001:00000330  ??0Vec8f@@QAE@XZ                  avx.obj <-- avx version used
0001:00000350  ??BVec8f@@QBE?AT__m256@@XZ        avx.obj
0001:00000380  ?load@Vec8f@@QAEAAV1@PBM@Z        avx.obj <-- avx version used
0001:00000580  ?func_sse2@@YAMPBM@Z              sse2.obj
0001:00000670  ??0Vec256fe@@QAE@XZ               sse2.obj
0001:00000690  ??0Vec4f@@QAE@ABT__m128@@@Z       sse2.obj
0001:000006c0  ??BVec4f@@QBE?AT__m128@@XZ        sse2.obj
0001:000006f0  ?get_high@Vec8f@@QBE?AVVec4f@@XZ  sse2.obj
0001:00000720  ?get_low@Vec8f@@QBE?AVVec4f@@XZ   sse2.obj

至于修复它,那是另一回事了。在这种情况下,以下直率的 hack 应该通过强制 avx 版本拥有自己的模板函数的不同命名版本来起作用。这将增加生成的可执行文件的大小,因为即使 sse2 和 avx 版本相同,它将包含同一函数的多个版本。

// avx.cpp
namespace AVXWrapper {
\#include "vectorclass.h"
}
using namespace AVXWrapper;

float func_avx(const float* a)
{
    ...
}

但有一些重要的限制 - (a) 如果包含的文件管理任何形式的全局状态,它将不再是真正的全局,因为您将有 2 个“半全局”版本,并且 (b) 您将无法将向量类变量作为参数在 avx.cpp 中定义的其他代码和函数之间传递。

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

适用于 AVX 和 SSE 的 Visual Studio 的 cpu 调度程序 的相关文章

  • 秒表有最长运行时间吗?

    多久可以Stopwatch在 NET 中运行 如果达到该限制 它会回绕到负数还是从 0 重新开始 Stopwatch Elapsed返回一个TimeSpan From MSDN https learn microsoft com en us
  • 在哪里可以找到列出 SSE 内在函数操作的官方参考资料?

    是否有官方参考列出了 GCC 的 SSE 内部函数的操作 即 头文件中的函数 除了 Intel 的 vol 2 PDF 手册外 还有一个在线内在指南 https www intel com content www us en docs in
  • ASP.NET MVC:这个业务逻辑应该放在哪里?

    我正在开发我的第一个真正的 MVC 应用程序 并尝试遵循一般的 OOP 最佳实践 我正在将控制器中的一些简单业务逻辑重构到我的域模型中 我最近一直在阅读一些内容 很明显我应该将逻辑放在域模型实体类中的某个位置 以避免出现 贫血域模型 反模式
  • 查找c中结构元素的偏移量

    struct a struct b int i float j x struct c int k float l y z 谁能解释一下如何找到偏移量int k这样我们就可以找到地址int i Use offsetof 找到从开始处的偏移量z
  • 堆栈溢出:堆栈空间中重复的临时分配?

    struct MemBlock char mem 1024 MemBlock operator const MemBlock b const return MemBlock global void foo int step 0 if ste
  • C#中如何移动PictureBox?

    我已经使用此代码来移动图片框pictureBox MouseMove event pictureBox Location new System Drawing Point e Location 但是当我尝试执行时 图片框闪烁并且无法识别确切
  • 重载<<的返回值

    include
  • 使用 Bearer Token 访问 IdentityServer4 上受保护的 API

    我试图寻找此问题的解决方案 但尚未找到正确的搜索文本 我的问题是 如何配置我的 IdentityServer 以便它也可以接受 授权带有 BearerTokens 的 Api 请求 我已经配置并运行了 IdentityServer4 我还在
  • 转发声明和包含

    在使用库时 无论是我自己的还是外部的 都有很多带有前向声明的类 根据情况 相同的类也包含在内 当我使用某个类时 我需要知道该类使用的某些对象是前向声明的还是 include d 原因是我想知道是否应该包含两个标题还是只包含一个标题 现在我知
  • 使用 x509 证书签署 json 文档或字符串

    如何使用 x509 证书签署 json 文档或字符串 public static void fund string filePath C Users VIKAS Desktop Data xml Read the file XmlDocum
  • 覆盖子类中的字段或属性

    我有一个抽象基类 我想声明一个字段或属性 该字段或属性在从该父类继承的每个类中具有不同的值 我想在基类中定义它 以便我可以在基类方法中引用它 例如覆盖 ToString 来表示 此对象的类型为 property field 我有三种方法可以
  • 链接器错误:已定义

    我尝试在 Microsoft Visual Studio 2012 中编译我的 Visual C 项目 使用 MFC 但出现以下错误 error LNK2005 void cdecl operator new unsigned int 2
  • 如何使用 C# / .Net 将文件列表从 AWS S3 下载到我的设备?

    我希望下载存储在 S3 中的多个图像 但目前如果我只能下载一个就足够了 我有对象路径的信息 当我运行以下代码时 出现此错误 遇到错误 消息 读取对象时 访问被拒绝 我首先做一个亚马逊S3客户端基于我的密钥和访问配置的对象连接到服务器 然后创
  • 为什么编译时浮点计算可能不会得到与运行时计算相同的结果?

    In the speaker mentioned Compile time floating point calculations might not have the same results as runtime calculation
  • 通过指向其基址的指针删除 POD 对象是否安全?

    事实上 我正在考虑那些微不足道的可破坏物体 而不仅仅是POD http en wikipedia org wiki Plain old data structure 我不确定 POD 是否可以有基类 当我读到这个解释时is triviall
  • 是否可以在 .NET Core 中将 gRPC 与 HTTP/1.1 结合使用?

    我有两个网络服务 gRPC 客户端和 gRPC 服务器 服务器是用 NET Core编写的 然而 客户端是托管在 IIS 8 5 上的 NET Framework 4 7 2 Web 应用程序 所以它只支持HTTP 1 1 https le
  • IEnumreable 动态和 lambda

    我想在 a 上使用 lambda 表达式IEnumerable
  • 如何将服务器服务连接到 Dynamics Online

    我正在修改内部管理应用程序以连接到我们的在线托管 Dynamics 2016 实例 根据一些在线教程 我一直在使用OrganizationServiceProxy out of Microsoft Xrm Sdk Client来自 SDK
  • 如何在文本框中插入图像

    有没有办法在文本框中插入图像 我正在开发一个聊天应用程序 我想用图标图像更改值 等 但我找不到如何在文本框中插入图像 Thanks 如果您使用 RichTextBox 进行聊天 请查看Paste http msdn microsoft co
  • 使用.NET技术录制屏幕视频[关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 有没有一种方法可以使用 NET 技术来录制屏幕 无论是桌面还是窗口 我的目标是免费的 我喜欢小型 低

随机推荐

  • 通过 REST 发布 NIFI 模板?

    我有多个 nifi 服务器 我希望能够通过脚本的 REST 接口将模板发布到这些服务器 The controller templates endpoint appears to be the proper REST endpoint to
  • 使用 Jenkins Git 插件中的 SSH 密钥在构建期间运行 Git 命令

    我们在 Jenkins 上的构建作业作为发布构建的一部分运行一些 git 命令 例如 git push 和 git pull 因此需要一种在构建期间从 shell 运行经过身份验证的 git 命令的方法 我们的詹金斯奴隶不持有任何凭证 因为
  • 如何在 Firefox 和 Chrome 中选择文档模式而不设置 DOCTYPE?

    我正在努力将使用旧网络标准创建的网页转换为支持现代网络浏览器 目前 该网页在 Internet Explorer 9 Firefox 和 Chrome 中以 Quirks 模式呈现 在 IE9 中 我可以选择 文档模式 在其中呈现我正在查看
  • LibGDX - 正确使用 Polygon 类

    我创造了Polygon包裹我的飞机的物体 飞机的大小TextureRegion是 256x74 但在游戏中这个尺寸是 70x20 所以 TextureRegion texRegsAirplane TextureRegion split te
  • 每个进程是否都存在内核堆栈?

    每个用户空间进程是否都存在一个内核堆栈和一个用户空间堆栈 如果两个堆栈都存在 那么每个用户空间进程应该有 2 个堆栈指针 对吗 在 Linux 中 每个任务 用户空间或内核线程 都有一个 8kb 或 4kb 的内核堆栈 具体取决于内核配置
  • 将 git 与 svn 一起使用的好习惯

    Subversion 几年前就很流行 现在 git 也开始流行 越来越多的人想用 git 取代 Subversion 问题是很多项目都是基于 Subversion 的 所以问题是如何将 git 与 Subversion 一起使用 不要完全取
  • PHP启动:无法使用Jenkins加载动态库'/usr/lib/php/20160303/pdo_sqlite.so'

    在 Jenkins 管道中运行 phpunit 测试套件时 我收到此警告 PHP Warning PHP Startup Unable to load dynamic library usr lib php 20160303 pdo sql
  • 常规文件读取可以从非阻塞 IO 中受益吗?

    对我来说似乎不是 我找到了一个支持我的观点的链接 http www remlab net op nonblock shtml 你怎么认为 您发布的链接内容是正确的 以非阻塞模式打开的常规文件套接字将始终 准备好 读取 当您实际尝试读取它时
  • 使用 mysql 变量保存用于 where in 子句的逗号分隔值

    我必须运行这样的查询 查询 1 select something from sometable where someId in 1 2 3 我想为 ID 部分保留一个变量 如下所示 查询 2 set myIds 1 2 3 select s
  • 如何在 C# 中使用 foreach 枚举哈希表

    我试图列举一个Hashtable其定义为 private Hashtable keyPairs new Hashtable foreach SectionPair s in keyPairs if s Section incomingSec
  • ExtJS 中的面包屑导航

    如何在 ExtJS 设计中显示面包屑功能 我正在使用带有边框布局的面板 我想在面板顶部设计碎屑功能 请寄给我一些样品 提前致谢 我想到了两种解决方案 使用面板标题 您将必须操纵面板的标题并在其上创建面包屑 您必须创建面包屑文本 并将其设置为
  • 为什么在网关取消的订单状态没有转换为“ payment_pending ”?

    我正在使用 Magento 社区 ver1 6 1 0 我在 Magento wiki 上找到了这个状态图http www magentocommerce com wiki 2 magento concepts and architectu
  • 如何在不访问该页面的情况下每分钟自动运行php脚本?

    我正在开发网站 当用户注册我的网站时 该网站会自动向用户发送电子邮件 我在网上搜索过 大多数人说我必须使用cron jobs 现在困扰我的大问题是关于 cron 作业的 我不知道如何编写它 也不知道如何执行它 谁能给我一些关于它的例子吗 预
  • 如何从 JtextPane 获取样式?

    我有一个带有格式化文本的 JtextPane 我需要复制完整的样式和属性 从此文本将其传输到另一个 JtextPane 有示例或代码片段吗 看看它是如何工作的 好的 这是我找到的代码 我做了一些更改 import java awt impo
  • 如何在 Android Studio 中或通过 ADB 获取 Android Things 设备上的应用程序的屏幕截图?

    有什么办法可以截图吗Android Studio 或通过ADB 适用于 Raspberry Pi 3 B 型Android Things 开发者预览版 https developer android com things hardware
  • 将焦点返回到主窗体

    我有一个带有两种表单的 C 应用程序 第一个是主窗体 应始终打开 第二个是用户可以启用的预览窗格 当用户选择显示预览窗格 菜单选项 时 预览窗格将打开 这就是我想要的 但是我想防止预览窗格获得焦点 否则 如果用户想要访问菜单 位于主窗体上
  • 加载实体实例需要超过 1 秒

    我在EF中遇到了一件有趣的事情 如果我们使用基础实体获取子实体 则加载实体需要更多时间 我的模型看起来像这样 public abstract class BaseDocument public Guid Id get set public
  • 如何阻止 MailApp.sendEmail() 每约 80 个字符向电子邮件正文添加换行符?

    我正在使用附加到我的 Google 云端硬盘中的 google 工作表的 google 脚本来发送电子邮件 我注意到 MailApp sendEmail 发送的电子邮件的正文与原来的不太一样 它每约 75 个字符添加一个换行符 不中断单词
  • 指定 jQuery 验证插件中验证器的顺序

    我想知道是否可以指定验证器的运行顺序 目前 我编写了一个自定义验证器来检查它是否为 a zA Z0 9 以确保登录验证我们的规则 并编写了一个远程验证器以确保登录可用 但目前远程验证器是在我的自定义之前启动的验证器 仅当元素验证我的自定义验
  • 适用于 AVX 和 SSE 的 Visual Studio 的 cpu 调度程序

    我使用两台计算机工作 一种不支持 AVX 另一种支持 AVX 让我的代码在运行时找到我的CPU支持的指令集并选择合适的代码路径会很方便 我按照 Agner Fog 的建议制作了一个 CPU 调度程序 http www agner org o