适用于 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 调度程序 的相关文章

  • 运行应用程序时.NET 3.5 JIT 不工作

    以下代码在 Visual Studio 内部运行该版本和在 Visual Studio 外部运行该版本时提供不同的输出 我正在使用 Visual Studio 2008 并面向 NET 3 5 我也尝试过 NET 3 5 SP1 在 Vis
  • BufferBlock 连续

    我想使用以下方式实现消费者 生产者模式BufferBlock
  • 是否有可能将 *.pdb 文件包含到发布版本中以查看错误行号?

    我做了一个项目 所有设置都是默认的 当我在调试模式 构建配置 调试 下运行它并遇到异常时 它转储到我的自定义日志记录机制 其中包含错误行号 但是当我运行发布构建时 记录相同的异常 没有行号 只有方法抛出和记录调用堆栈 是否有可能在发布配置
  • std::bind2nd 和 std::bind 与二维数组和结构数组

    我知道 C 有 lambda 并且 std bind1st std bind2nd 和 std bind 已弃用 然而 从C 的基础开始 我们可以更好地理解新特性 所以 我从这个非常简单的代码开始 使用int 数组s 第一个例子 与std
  • 如何从 C# 调用 F# 类型扩展(静态成员函数)

    FSharp 代码的结构如下 我无法控制源代码 namespace FS
  • 为什么我在 WinForms 列表框中得到“System.Data.DataRowView”而不是实际值?

    每当我运行代码并尝试查看highscore我在列表框中得到的只是System Data DataRowView 谁能明白为什么吗 Code MySqlConnection myConn new MySqlConnection connStr
  • C#生成的csv文件通过电子邮件发送嵌入到Lotus Note中电子邮件的底部

    我遇到了一个奇怪的问题 即使用 NET SmtpClient 通过电子邮件发送的 CSV 附件出现在电子邮件底部 而不是 Lotus Note 中的附件 我只是不知道如何解决这个问题 而且我无法访问客户端计算机 这使得调试非常困难 我可以采
  • 从 Golang 调用 C 函数

    我想在 Golang 中编写控制器逻辑并处理 json 和数据库 同时在 C 中使用我的数学处理模型 在我看来 调用 C 函数的开销必须尽可能低 就像设置寄存器 rcx rdx rsi rdi 一样 执行一些操作fastcall 并获取 r
  • 根据 Active Directory 策略检查密码[重复]

    这个问题在这里已经有答案了 我有一个允许用户更改其 AD 密码的前端 有没有办法获取特定用户及其属性 长度 复杂性 的密码策略 例如细粒度 有没有办法根据此特定策略检查字符串 xyz121 编辑 我不想检查活动目录中存储的当前密码 我想检查
  • Web 文本编辑器中的 RTF 格式

    网络上是否有支持 RTF 格式文档输入的文本编辑器 我知道这对 webdev 来说有点奇怪 但我需要从数据库中读取 RTF 文档 并在基于 Web 的文本编辑器中对其进行编辑 然后将其存储回 RTF 中 在我在转换工具上投入太多资金之前 我
  • 在 Windows 上使用 C/C++ 开发时省略 msvcr100.dll?

    是否可以在 Windows 上使用 C C 进行开发而不链接到 msvcr100 dll 我知道这是 Windows 的标准 c 库 但我想知道如果我没有安装 Visual Studio 或 Redistributable 软件包 我的计算
  • 文本框中“结束编辑”的事件

    我正在 winform c 中使用文本框 并使用文本在数据库中进行查询 但每次文本更改时 我都需要不断查阅文本框的文本 因此 对于这些 我使用 KeyUp 但这个活动太慢了 文本框编辑完成后是否会触发任何事件 我考虑完成2个条件 控制失去焦
  • XCode std::thread C++

    对于学校的一个小项目 我需要创建一个简单的客户端 服务器结构 它将在路由器上运行 使用 openWRT 并且我试图在这个应用程序中使用线程做一些事情 我的 C 技能非常有限 所以我在internet https stackoverflow
  • 按 Enter 继续

    这不起作用 string temp cout lt lt Press Enter to Continue cin gt gt temp cout lt lt Press Enter to Continue cin ignore 或更好 in
  • 如何使用“路径”查询 XDocument?

    我想查询一个XDocument给定路径的对象 例如 path to element I want 但我不知道如何继续 您可以使用以下方法System Xml XPath Extensions http msdn microsoft com
  • C# 模式匹配

    我对 C 有点陌生 我正在寻找一个字符串匹配模式来执行以下操作 我有一个像这样的字符串 该书将在 唐宁街 11 号接待处 并将由主要医疗保健人员参加 我需要创建一个 span 标签来使用 startIndex 和 length 突出显示一些
  • Web API 2.0 使用 pascalcase 模型接收驼峰式命名的 JSON 数据

    我正在尝试对我的 Web API 进行 PUT 调用 我在 WebApiConfig cs 中设置了以下内容 以处理以驼峰形式将数据发送回我的 Web 项目 config Formatters JsonFormatter Serialize
  • 如何获取运行或段落的高度

    我找到了Run or Paragraph in FlowDocument现在我需要知道HEIGHT of it i e while navigator CompareTo flowDocViewer Document ContentEnd
  • boost::spirit::qi::语法和可变参数模板

    我在使用可变参数模板定义语法时面临一个问题 我首先定义一些包含在某些结构中的简单语法 例如纬度 经度 如下所示 include
  • 线程安全的有限大小队列,不使用锁

    我正在尝试编写一个主题队列 但遇到死锁和其他多线程问题 我想用Interlocked CompareExchange避免lock用法 但这段代码并没有按预期工作 它只是擦除整个队列 我在这里做错了什么 public class FixedS

随机推荐

  • 通过 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