gpt4 book ai didi

c++ - 物理寄存器和英特尔 SIMD 变量之间的关系?

转载 作者:塔克拉玛干 更新时间:2023-11-03 06:45:37 28 4
gpt4 key购买 nike

物理处理器寄存器与英特尔内部函数(例如 __m128)中使用的变量之间的关系是什么?

解释 SIMD 的图表通常显示 2 个寄存器,但引用了 Intel forums “注册压力”并在此question “注册着色”表明还有更多事情正在发生。

可以声明任意数量的代表寄存器的变量吗?当它们与有限的物理资源紧密相关时,这怎么可能呢?关于如何选择物理寄存器,应该注意什么?如果声明的寄存器多于存在的寄存器会怎样?

可以同时激活多对寄存器吗?

是否有不同类型的物理寄存器?

最佳答案

_m128, _m128i, _m128d, ... 等变量类型主要是为了保护你。它们确保您不会尝试使用 +、-、&、|、== 等标准运算符,并确保如果您尝试分配错误的类型,编译器将抛出错误。这些类型强制编译器将自身加载到适当的寄存器(在本例中为 XMM*),但仍然允许编译器自由选择哪一个,或者如果所有适当的寄存器都被占用,则将它们存储在本地堆栈中。它们还确保无论何时将它们存储在堆栈中,它们都保持正确的对齐(在本例中为 16 字节对齐),以便依赖对齐的内部指令不会导致 GPF。

如果您喜欢使用 asm 结构,您可以将这些变量之一紧密地绑定(bind)到物理寄存器:

__m128i myXMM1 asm( "%xmm1");

但最好让编译器发挥它的魔力并为您选择寄存器以实现更好的优化。

可以声明任意数量的这些变量,即使超额预订您的 XMM 寄存器存储也可能不会导致使用堆栈空间,只要您的工作寄存器集保持较小。编译器作用域通常会意识到何时不再使用某个值,并允许优化器不将其存储回堆栈。有时您可以通过创建自己的作用域堆栈框架来帮助编译器:

__m128i storedVar;
{
__m128i tempVar1, tempVar2, tempVar3;
// do some operations with tempVar1 -> 3
storedVar = tempVar1;
}
{
__m128i tempVar4, tempVar5, tempVar6, tempVar7, tempVar8;
// do some operations with tempVar4 -> 8
storedVar = tempVar4;
}

return storedVar;

由于变量在闭合的花括号处超出范围,编译器发现用于包含这些值的寄存器现在已被释放,因此它不需要超过可用 XMM 寄存器的总数。

如果你确实超额预订你的寄存器存储,并且所有值都需要维护,那么编译器将在堆栈上分配适当的大小并确保它正确对齐,并且 XMM 寄存器的值将被换出到堆栈为新值腾出空间。请记住,堆栈空间缓存良好,因此写入和读取不会像您预期的那样有害。真正的打击是需要额外的移动操作来换入和换出它们。

物理寄存器按宽度有不同类型(64位、128位、256位、512位),显然与对应的C/C++内在数据类型有关。给定宽度的不同“ flavor ”(“__m128i”、“__m128d”、...)实际上可以驻留在给定宽度的任何寄存器中。该类型强制您使用适当的内部类型(例如,_mm_and_si128_mm_and_pd),这反过来会生成适当版本的指令。

像“and”这样的东西就是一个很好的例子,因为无论类型如何,结果操作都是相同的 - 按位“and”。但是根据我在英特尔文档中阅读的内容,使用错误的类型可能会导致延迟。整数指令和浮点指令有单独的执行队列,每当数据必须从一个执行队列移动到另一个执行队列时,就会有惩罚。因此,一般来说,最好选择合适的数据类型,以便生成合适的指令,并保持在该数据类型的范围内。

关于c++ - 物理寄存器和英特尔 SIMD 变量之间的关系?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22207021/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com