- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
是否存在强制 C 编译器直接使用内存操作数的语法?
在过去美好的 asm 时代,我们只需在指令中写入操作数的位置 - “真实”寄存器或内存指针(由地址指向的位置)。
但在 C 的内在函数伪汇编中,我看不到强制编译器在指令中使用内存指针的方法(拒绝从内存(缓存)加载数据到“寄存器”,即垃圾寄存器文件加载内容到缓存和导致重新加载并受到惩罚)。
我知道程序员很容易简单地将“可变”操作数写入 instinsic 并让编译器决定是先从内存加载还是直接使用它(如果可能)。
当前任务:我想计算 AVX2 CPU 上一系列 8x8 8 位 block 的 SAD,其中包含 512 字节的寄存器文件(16 个 ymm“寄存器”,每个 32 字节)。因此它可以加载 8 个 8x8 8 位源 block 以完全填充可用的 AVX2 寄存器文件。
我想在所有 寄存器文件中加载源 block ,并针对这些源 block 和每个引用位置仅测试内存中的不同“引用”位置一次。所以我想阻止 CPU 从缓存中加载 ref block 到寄存器文件,并在 sad 指令中使用“内存操作数”。
使用 asm 我们可以简单地写一些类似的东西
(load all 16 ymm registers with src)
vpsadbw ymm0, ymm0, [ref_base_address_register + some_offset...]
但是在 C 文本中它是内在的
__m256i src = load_src(src_pointer);
__m256i ref = load_ref(ref_pointer);
__m256i sad_result= _mm256_sad_epu8(src, ref)
它没有办法让编译器使用有效的内存操作数
__m256i src = load_src(src_pointer);
__m256i sad_result= _mm256_sad_epu8(src, *ref_pointer)
或者取决于“任务大小”,如果编译器用完可用寄存器,它将自动切换到内存操作数版本,程序员可以编写
__m256i sad_result=_mm256_sad_epu8(*(__m256i*)src_pointer, *(__m256i*)ref_pointer)
并期望编译器将加载 2 个操作数之一到寄存器文件并使用内存中的下一个?
最佳答案
不,没有,除了一些具有指针操作数的特定内在函数,即使它们不是纯加载或纯存储1。
内在函数的部分目的是抽象出寄存器分配细节,就像它对 int
或 double
所做的那样,因此由编译器将内容保留在当这是一件好事时注册。这通常会发生,因此,如果您担心优化器未能将负载内在函数折叠到内存源操作数(例如在 https://godbolt.org/ 上或本地),请检查 asm 输出。 AVX(VEX 编码)甚至允许折叠未对齐的负载,因为与传统 SSE 不同,默认情况下不需要对齐。
当编译器失败时,这可能会很糟糕,就像许多用于 _mm256_cvtepu8_epi32( _mm_loadl_epi64(p) )
的编译器一样 - GCC 用于发出实际的 movq
加载和 reg -reg vpmovzxbd
。只有在 GCC9 及更高版本中,我们才能获得内存源 vpmovzxbd
。 ( Loading 8 chars from memory into an __m256 variable as packed single precision floats )
或者对于您的情况,如果编译器溢出了错误的东西,唯一的解决方法是提交优化错误报告并等待新的编译器版本。或者用 asm 编写一个版本(内联或独立)。
内在模型的设计者还想提供 load
/loadu
和 store
/storeu
内在函数将对齐信息传达给编译器。 (对于 float/double,在 float*
和 __m128*
或其他任何东西之间进行转换。)_mm_load_si128((__m128i*)foo)
是 < em>完全与 *(__m128i*)foo
完全相同并且与访问 __m128i
数组的元素几乎相同,如果编译器不能查看数组并将其保存在寄存器中。参见 Is `reinterpret_cast`ing between hardware SIMD vector pointer and the corresponding type an undefined behavior?
令人困惑的是,加载内在函数看起来像 asm 加载/存储,但在启用优化时它们实际上根本不同。
脚注 1:AVX-512 有一些特殊指令,这些指令具有相应有趣的内在函数,如 VPMOVDB mem128 {k}, zmm2
- void _mm512_mask_cvtepi32_storeu_epi8(void * d, __mmask16 k, __m512i a);
。能够存储到内存为 Xeon Phi(骑士登陆)提供了一种在没有 AVX-512BW 的情况下为 vmovdqu8
进行字节屏蔽存储的方法。
关于c - 强制编译器使用 Intrinsics 中的内存操作数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70261138/
在 Intel Intrinsics Guide 中,在几个 Intrinsics 的底部有“延迟和吞吐量信息”,列出了几个 CPUID 的性能。 例如,Intrinsics Guide 中的表格对于
Intel Intrinsics Guide表示内在 _mm256_rsqrt_ps 的相对误差至多为 1.5*2^-12。但是,当我将 _mm256_rsqrt_ps 的结果与平方根倒数的标准 C+
我正在尝试使用内在函数编写 AVX2 代码。想知道如何使用 Intel 内在函数将 YMM 中的最低字广播到整个 YMM。我知道用汇编代码我可以写 vpbroadcastw ymm1, xmm0 因为
我在 Intel Intrinsic Guide v2.7 中找不到它们。您知道 AVX 或 AVX2 指令集是否支持它们吗? 最佳答案 原始 AVX 指令集中没有分散或收集指令。 AVX2 添加了收
是否存在强制 C 编译器直接使用内存操作数的语法? 在过去美好的 asm 时代,我们只需在指令中写入操作数的位置 - “真实”寄存器或内存指针(由地址指向的位置)。 但在 C 的内在函数伪汇编中,我看
https://web.archive.org/web/20170227190422/http://hilbert-space.de/?p=22 在这个过时的网站上,它表明手写 asm 会比内在函数带
我使用英特尔内在函数具有以下函数: int c_lattice_worker( int lm, double* inArr, double* outArr, int arrLen,
所以我试图将一个常量与短 int a[101] 与英特尔内在函数相乘。我已经用加法完成了它,但我似乎无法弄清楚为什么它不适用于乘法。另外,在我们使用 32 位整数之前,现在我们使用 16 位短整数,因
我对内在函数、simd 和一般的低级编程真的一窍不通。我正在迈出第一步,但就我所见,我正在使用的所有内部函数(Intel ones 现在)只是 C++ 通用代码,没有任何“特殊”或专用关键字。 这似乎
我一直在试验 SSE 内在函数,我似乎遇到了一个我无法弄清楚的奇怪错误。我正在计算两个 float 组的内积,一次计算 4 个元素。 为了测试,我将两个数组的每个元素都设置为 1,因此乘积应该是 ==
如何正确使用 RenderScript Intrinsics。 如图http://android-developers.blogspot.com/2013/08/renderscript-intrin
我正在尝试优化一些循环并且我已经成功了,但我想知道我是否只做了部分正确的事情。比如说我有这个循环: for(i=0;i int main() { int i{0}; float a[1
我的问题是当头文件包含在 SDK 中(从 VC 10 安装)并且我用来编译驱动程序的 WDK 不了解时,如何在内核空间(在 Windows 上)使用内部函数这个文件。当我 #include 一切正常,
我正在使用 SSE 对图像中的像素执行按位非运算。 我有一些问题: 可以使用 OpenMP 进一步优化吗? 我的算法中是否存在可以优化的瓶颈? 这是我的代码: unsigned int iSSE2Si
我最近一直在使用 SSE 内部 int _mm_extract_epi8 (__m128i src, const int ndx),根据引用“从索引选择的压缩整数数组元素中提取整数字节” .这正是我想
只是想知道#pragma intrinsic(_m_prefetchw) 是什么意思? 最佳答案 据我所知,看起来有人打算修改某些 MSVC++ 特定设置。但是,该设置不是 intrinsic pra
我有以下代码: #include #include #include long long lzcnt(long long l) { return __lzcnt64(l); } int
浏览Kotlin源码时,发现有些地方会抛出NotImplementedError: public suspend inline val coroutineContext: CoroutineConte
我正在尝试通过阅读 Intel Intrinsics Guide 来开始使用 AVX512 内在函数但到目前为止我发现它没有定义命名数据类型或用于解释的伪代码语法。没有这样的定义,所谓的指南对我起码没
java.lang.StackOverflowError at kotlin.jvm.internal.Intrinsics.areEqual(Intrinsics.java:164)
我是一名优秀的程序员,十分优秀!