我一直在阅读div和mul组装操作,我决定通过在C中编写一个简单的程序来实现它们:
#include <stdlib.h>
#include <stdio.h>
int main()
{
size_t i = 9;
size_t j = i / 5;
printf("%zu\n",j);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
然后生成汇编语言代码:
gcc -S division.c -O0 -masm=intel
Run Code Online (Sandbox Code Playgroud)
但是看生成的division.s文件,它不包含任何div操作!相反,它通过位移和魔术数字来做某种黑魔法.这是一个计算代码片段i/5:
mov rax, QWORD PTR [rbp-16] ; Move i (=9) to RAX
movabs rdx, -3689348814741910323 ; Move some magic number to RDX (?)
mul rdx ; Multiply 9 by magic number
mov rax, rdx ; Take only the upper 64 bits of the …Run Code Online (Sandbox Code Playgroud) 浮点值除法有_mm_div_ps,整数乘法有_mm_mullo_epi16.但是有什么整数除法(16位值)?我怎么进行这种划分?
我正在寻找一些SSE / AVX建议,以优化将RGB通道与其alpha通道预乘的例程:RGB * alpha / 255(+我们保留原始的alpha通道)。
for (int i = 0, max = width * height * 4; i < max; i+=4) {
data[i] = static_cast<uint16_t>(data[i] * data[i+3]) / 255;
data[i+1] = static_cast<uint16_t>(data[i+1] * data[i+3]) / 255;
data[i+2] = static_cast<uint16_t>(data[i+2] * data[i+3]) / 255;
}
Run Code Online (Sandbox Code Playgroud)
您会在我当前的实现下面找到它,但是我认为它可能会更快,而且我正在浪费宝贵的CPU周期。我在quick-bench.com上进行了测试,结果显示出令人鼓舞的效果,但是我应该做些什么改变才能使其快速发展呢?
谢谢
--------更新09/06/2019 --------
根据@chtz和@Peter Cordes的评论,我建立了一个存储库来评估不同的解决方案,这里是结果。您认为会更好吗?
Run on (8 X 3100 MHz CPU s)
CPU Caches:
L1 Data 32K (x4)
L1 Instruction 32K (x4)
L2 Unified 262K (x4)
L3 Unified 8388K (x1) …Run Code Online (Sandbox Code Playgroud) 我有一个c ++(或类似c的)函数,在该函数下尝试进行矢量化处理。该功能是图像合成的多种变体之一,其中它采用带有色度444二次采样的Y,U或V图像平面,并将src图像合成/叠加到dst图像上(其中src图像还包含alpha透明度)。
#include <cstdint>
void composite(uint8_t *__restrict__ pSrc, // Source plane
uint8_t *__restrict__ pSrcA, // Source alpha plane
uint8_t *__restrict__ pDst, // Destination plane
const std::size_t nCount) // Number of component pixels to process.
{
for (std::size_t k = 0; k < nCount; ++k)
{
uint16_t w = (pSrc[k] * pSrcA[k]);
uint16_t x = (255 - pSrcA[k]) * pDst[k];
uint16_t y = w+x;
uint16_t z = y / uint16_t{255};
pDst[k] = static_cast<uint8_t>(z);
}
}
Run Code Online (Sandbox Code Playgroud)
在AVX2向量化等效项中,我正在努力了解如何有效地读取8位转换为16位,以及(在处理/合成之后)最终将16位样本转换回8位以存储回内存。在读取方面,我使用的是中间的xmm寄存器-似乎不是最好的方法。我猜想混合寄存器系列会降低性能。
我想出了(不完整):
#include <cstdint>
#include <immintrin.h> …Run Code Online (Sandbox Code Playgroud)