- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我对内在函数、simd 和一般的低级编程真的一窍不通。我正在迈出第一步,但就我所见,我正在使用的所有内部函数(Intel ones 现在)只是 C++ 通用代码,没有任何“特殊”或专用关键字。
这似乎是那些“函数列表”和编译器之间的一种协议(protocol),例如告诉编译器如果我使用这样的东西:
__m128d vA = _mm_load_pd(a);
它应该将vA
变量视为XMM
寄存器,而不是将其分配到内存中。但它不能保证(因为 __m128d
,最后,它是一个 C++ union/结构对象,可以驻留在内存中)。
我说的对吗?或者引擎盖下还有更多的黑魔法?
Compiler 如何“以某种方式”处理这些函数而不是通用函数?通过解析代码匹配的规则?像这样的东西?
它对 Web 开发人员来说非常有吸引力 :)
最佳答案
您实际上是在问两个不同的问题:
(1) 编译器如何决定将我的 SIMD 变量放在哪里?在内存中还是在寄存器中?
(2) 内在的“契约”有多具体?它是否总是发出特定指令?
第一个问题的答案对于 SIMD 与任何其他类型的变量并没有什么不同。在 C/C++ 中,通常使用 automatic variables因为这些最有可能最终出现在寄存器中。编译器可以根据上下文自由安排实际指令和寄存器使用,并且通常会根据代码中的“寄存器压力”大小将数据移入和移出寄存器以“堆栈内存”。
与在汇编中编写它相比,这种灵 active 是一件“好事”,在汇编中,程序员可以确切地决定在何时使用哪些寄存器以及以什么顺序执行指令。编译器通常可以混合其他附近的代码或做其他难以保持直线的优化,它可以利用架构差异。例如,在 DirectXMath 中我为 x86(32 位)和 x64(64 位)编写了相同的内部代码,编译器可以使用 x64 中可用的 8 个额外寄存器。如果我使用内联汇编,我将不得不以两种不同的方式编写它,并且可能不止于此,我很快就会谈到一些额外的差异。
When writing SIMD code, you really want to maximize the work with data already in a register because the load/store overhead to memory often costs as much performance as you get from doing a few SIMD instructions vs. scalar. As such, you will usually write SIMD intrinsics to do an explicit load into a bunch of 'automatic variables' but keep in mind that likely only 8 or so of them are going to really be in a register at a time. You do want to do enough work that the compiler can fill in the gaps. You then store the result to memory. As such, you really don't do stuff like
auto a = new __m128d;
. There's also the additional complexity of the implied aligment (__m128d
must be 16-byte aligned, and while x64new
does that x86new
does not).
第二个答案有点复杂。一个给定的内在函数通常被定义为一个给定的指令,一些内在函数实际上是指令的组合,但是编译器在选择确切的指令时可能会选择使用目标平台的一些知识。下面是几个例子:
__m128 _mm_add_ps (__m128 a, __m128 b)
被定义为 SSE 指令 addps
并且通常如此发出。但是,如果您使用 /arch:AVX
或 /arch:AVX2
构建,编译器将使用 VEX prefix和指令 vaddps
。
__m128d _mm_fmadd_pd (__m128d a, __m128d b, __m128d c)
被定义为 FMA3 指令,但编译器实际上可以发出 vfmadd132pd
, vfmadd213pd
或 vfmadd231pd
取决于确切的寄存器使用。事实上,编译器甚至可以决定使用 vmulpd
后跟 vaddpd
更快,这取决于硬件指令成本函数的确切指令时间它正在使用。
Note that while it is certainly possible for the compiler implementer to decide say that they could optimize
__m128 _mm_shuffle_ps (__m128 a, __m128 b, unsigned int imm8)
where the registers a and b are the same and choose emit avpermilps
instead of ashufps
if you are building with/arch:AVX
. That would be 'in contract' with the intrinsic. In practice, however, intrinsics tend to be treated a bit special and strongly prefer the instruction they are defined as because you often use them in particular contexts based on hardware feature detection. So you normally can count on a particular instrinic to end up being the instruction you expect or a very close variant of it.
简而言之,所有 C/C++ 都是对编译器的“提示”,因为源代码描述了您想要的确切计算,但编译器可以自由地实际发出代码实现相同的结果,但顺序可能不同或使用与您可能假设的指令不同的指令。
The Intel Intrinsics Guide is a good resource for exploring intrinsics.
You might also find some of my blog posts related to intrinsics useful.
The DirectXMath Programmer's Guide also has some useful tricks & tips for intrinsics usage sprinkled throughout so it's worth a read and it's only 6 pages so it won't take that long. See Microsoft Docs
关于c++ - 声明 "intrinsics"只是对编译器的建议是否正确?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53762534/
我在覆盖 ReSwift Pod 中的函数时遇到问题。我有以下模拟类(class): import Foundation import Quick import Nimble import RxSwi
我有一个类似于下面的继承结构。我正在采用 Printable 协议(protocol)并努力覆盖 description 属性。我遇到了一个谷歌此时似乎不知道的奇怪错误,提示为第三类,并引用了第二类和
我有一个类“Cat”和 Cat 类的一个子类“DerivedCat”。 Cat 有一个函数 meow(),而 DerivedCat 覆盖了这个函数。 在应用程序中,我声明了一个 Cat 对象: Cat
Kotlin 变量 变量是用于存储数据值的容器。 要创建一个变量,使用 var 或 val,然后使用等号(=)给它赋值: 语法 var 变量名 = 值 val 变量名 = 值 示例 va
C 中的所有标识符在使用前都需要声明,但我找不到它在 C99 标准中表示的位置。 我觉得也是指宏定义,不过定义的只是宏展开顺序。 最佳答案 C99:TC3 6.5.1 §2,脚注 79 明确指出: T
今天我的博客提要显示错误: This page contains the following errors: error on line 2 at column 6: XML declaration
在编写 IIF 语句、表和下面给出的语句时出现错误。 陈述: SELECT IIF(EMP_ID=1,'True','False') from Employee; table : CREATE TAB
我正在创建一个登录 Activity ,我希望它在按下登录按钮时显示进度对话框,我声明、初始化并调用了它,但它没有显示。但是当我在创建时调用进度对话框时,它出现了 这是我的代码: public cla
当我输入声明语句时: Vector distance_vector = new Vector(); 我收到错误(在两种情况下都在“双”下划线): Syntax error on token "doub
我正在本地部署在docker-for-desktop中。这样我将来可以迁移到kubernetes集群。 但是我面临一个问题。使用永久卷时,docker容器/ pod中的目录将被覆盖。 我正在拉最新的S
我有一个 MyObject 类型的对象 obj,我声明了它的实例。 MyObject obj; 但是,我没有初始化它。 MyObject 的类看起来像: public class MyObject {
关闭。这个问题是opinion-based 。目前不接受答案。 想要改进这个问题吗?更新问题,以便 editing this post 可以用事实和引文来回答它。 . 已关闭 9 年前。 Improv
这个问题已经有答案了: Android: Issue during Arraylist declaration (1 个回答) 已关闭 9 年前。 有时我会看到 ArrayList 声明如下 Arra
我对java比较陌生,经过大量搜索,我无法将相关问题的任何解决方案与我的解决方案配对。我正在尝试实现一种非常简单的方法来写入/读取数组,但编译器无法识别它。 “键盘”也是一个“无法识别的变量”。这是数
简短:何时分配内存 - 在声明或初始化时? 长整型:int x;将占用与int z = 10;相同的内存。 此外,这对于包含更多数据的自定义对象将如何工作。假设我有这个对象: public class
我需要使用此程序更好地理解函数定义、声明和正确调用。我真的需要了解如何使用它们。您能否向我展示编写此程序的正确方法(所有三个都正确并进行解释)? #include #include quad_eq
这是我的主要功能以及我要传递的内容。 int main(void){ struct can elC[7]; // Create an array of stucts Initiali
我想知道是否有更好的方法来完成此任务; 我有一个对象 - 其中一个属性是字典。我有一组逗号分隔值。我需要过滤 Dictionary 并仅获取 Dictionary 值至少与其中一个值匹配的那些元素 这
下面的using-declarations有什么意义 using eoPop::size; using eoPop::operator[]; using eoPop::back; using eoPo
我的问题更像是一个关于 for 循环样式的好奇问题。在阅读别人的一些旧代码时,我遇到了一种我以前从未见过的风格。 var declaredEarlier = Array for(var i=0, le
我是一名优秀的程序员,十分优秀!