- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我从事 arm asm 已有一段时间,并尝试使用 x86 asm ssse3 优化简单循环。我找不到将大端转换为小端的方法。
ARM NEON 有一个单一的 vector 指令来执行此操作,但 SSSE3 没有。我尝试使用 2 个类次和一个或,但如果我们向左移动 8 位(数据饱和),则每个插槽需要 32 位而不是 16 位。
我查看了 PSHUFB,但是当我使用它时,16 位字的前半部分始终为 0。
我在 x86 for android 上使用内联汇编。对于语法不正确或可能出现的其他错误,我们深表歉意,请理解我的意思(很难从我的代码中删除它)。
# Data
uint16_t dataSrc[] = {0x7000, 0x4401, 0x3801, 0xf002, 0x4800, 0xb802, 0x1800,
0x3c00, 0xd800.....
uint16_t* src = dataSrc;
uint8_t * dst = new uint8_t[16] = {0};
uint8_t * map = new uint8_t[16] = { 9,8, 11,10, 13,12, 15,14, 1,0,3,2,5,4,7,6,};
# I need to convert 0x7000 to 0x0077 by shifting each 16 bit by its byte vectorized.
asm volatile (
"movdqu (%0),%%xmm1\n"
"pshufb %2,%%xmm1\n"
"movdqu %%xmm1,(%1)\n"
: "+r" (src),
"+r" (dst),
"+r" (map)
:
: "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4"
);
如果我遍历 dataSrc 变量,我的前 8 个字节的输出是:
0: 0
1: 0
2: 0
3: 0
4: 72
5: 696
6: 24
7: 60
即使顺序错误,也只会交换最后 4 个。为什么前 4 个全为零?无论我如何更改 map ,第一个有时为 0 而接下来的 3 个始终为零,为什么?我做错了什么吗?
编辑
我弄清楚了为什么它不起作用, map 没有正确传递到内联 asm,我不得不为它释放一个输入变量。
对于关于 intrisics 与手写 asm 的其他问题。下面的代码是将16字节的视频帧数据YUV42010BE转成YUVP420(8位),问题是shuffle,如果我用little endian,那段就没有了。
static const char map[16] = { 9, 8, 11, 10, 13, 12, 15, 14, 1, 0, 3, 2, 5, 4, 7, 6 };
int dstStrideOffset = (dstStride - srcStride / 2);
asm volatile (
"push %%ebp\n"
// All 0s for packing
"xorps %%xmm0, %%xmm0\n"
"movdqu (%5),%%xmm4\n"
"yloop:\n"
// Set the counter for the stride
"mov %2, %%ebp\n"
"xloop:\n"
// Load source data
"movdqu (%0),%%xmm1\n"
"movdqu 16(%0),%%xmm2\n"
"add $32,%0\n"
// The first 4 16-bytes are 0,0,0,0, this is the issue.
"pshufb %%xmm4, %%xmm1\n"
"pshufb %%xmm4, %%xmm2\n"
// Shift each 16 bit to the right to convert
"psrlw $0x2,%%xmm1\n"
"psrlw $0x2,%%xmm2\n"
// Merge both 16bit vectors into 1 8bit vector
"packuswb %%xmm0, %%xmm1\n"
"packuswb %%xmm0, %%xmm2\n"
"unpcklpd %%xmm2, %%xmm1\n"
// Write the data
"movdqu %%xmm1,(%1)\n"
"add $16, %1\n"
// End loop, x = srcStride; x >= 0 ; x -= 32
"sub $32, %%ebp\n"
"jg xloop\n"
// End loop, y = height; y >= 0; --y
"add %4, %1\n"
"sub $1, %3\n"
"jg yloop\n"
"pop %%ebp\n"
: "+r" (src),
"+r" (dst),
"+r" (srcStride),
"+r" (height),
"+r"(dstStrideOffset)
: "x"(map)
: "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4"
);
我还没有抽出时间使用小端来实现内在函数的随机播放
const int dstStrideOffset = (dstStride - srcStride / 2);
__m128i mdata, mdata2;
const __m128i zeros = _mm_setzero_si128();
for (int y = height; y > 0; --y) {
for (int x = srcStride; x > 0; x -= 32) {
mdata = _mm_loadu_si128((const __m128i *)src);
mdata2 = _mm_loadu_si128((const __m128i *)(src + 8));
mdata = _mm_packus_epi16(_mm_srli_epi16(mdata, 2), zeros);
mdata2 = _mm_packus_epi16(_mm_srli_epi16(mdata2, 2), zeros);
_mm_storeu_si128( (__m128i *)dst, static_cast<__m128i>(_mm_unpacklo_pd(mdata, mdata2)));
src += 16;
dst += 16;
}
dst += dstStrideOffset;
}
可能编写不正确,但在 Android 模拟器(API 27)、x86(SSSE3 是最高的,i686)上使用默认编译器设置和添加的优化进行了基准测试(尽管在性能上没有差异)-Ofast -O3 - funroll-loops -mssse3 -mfpmath=sse 平均:
内部函数:1.9-2.1 毫秒手写:0.7-1ms
有什么办法可以加快速度吗?也许我写错了内在函数,是否有可能获得接近手写内在函数的速度?
最佳答案
您的代码不起作用,因为您将 map
的地址传递给了 pshufb
。我不确定 gcc 为此生成了什么代码,我根本无法想象它会编译。
对这类事情使用内联汇编通常不是一个好主意。相反,使用内部函数:
#include <immintrin.h>
void byte_swap(char dst[16], const char src[16])
{
__m128i msrc, map, mdst;
msrc = _mm_loadu_si128((const _m128i *)src);
map = _mm_setr_epi8(9, 8, 11, 10, 13, 12, 15, 14, 1, 0, 3, 2, 5, 4, 7, 6);
mdst = _mm_shuffle_epi8(msrc, map);
_mm_storeu_si128((_m128i *)dst, mdst);
}
除了更容易维护之外,这优化得更好,因为 unlinke 内联汇编,编译器可以内省(introspection)内部函数并就发出哪些指令做出明智的决定。例如,在 AVX 目标上,它可能会发出 VEX 编码的 vpshufb
而不是 pshufb
以避免由于 AVX/SSE 转换导致的停顿。
如果出于任何原因您不能使用内部函数,请像这样使用内联汇编:
void byte_swap(char dst[16], const char src[16])
{
typedef long long __m128i_u __attribute__ ((__vector_size__ (16), __may_alias__, __aligned__ (1)));
static const char map[16] = { 9, 8, 11, 10, 13, 12, 15, 14, 1, 0, 3, 2, 5, 4, 7, 6 };
__m128i_u data = *(const __m128i_u *)src;
asm ("pshufb %1, %0" : "+x"(data) : "xm"(* (__m128i_u *)map));
*(__m128i_u *)dst = data;
}
关于c++ - 尝试使用 x86 asm SSSE3 将大端转换为小端,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52054144/
我正在尝试在 Raspberry Pi(使用 C 编程)和 Arduino(使用 Arduino IDE)之间发送和接收数据。 根据我在互联网上可以找到的内容,它指出两者都是小端格式。 我在 teun
考虑这段代码: int a=0x10000001; char b; b=(char)a; printf("%#x \n",b); 在我的 PC 上它打印 0x01,我并不感到惊讶。它在 BIG END
我需要你的帮助。我想使用以下代码,因为我正在开发一个音频工具(仅适用于 .wav 文件),其主要功能是显示信号波形。大端和小端是我无法控制的元素。我认为以下代码解决问题的方式是正确的:- 如果音频文件
我有一个十六进制字符串,其内容为18000000,该字符串采用主机字节顺序(小端),我需要将其转换为网络字节顺序(大端)。生成的十六进制字符串将为 00000018。 总而言之,我需要转换180000
我有一个十六进制字符串,其内容为18000000,该字符串采用主机字节顺序(小端),我需要将其转换为网络字节顺序(大端)。生成的十六进制字符串将为 00000018。 总而言之,我需要转换180000
我有一个整数列表,比如说 L,它包含一个数字的二进制表示。列表L中的每个整数可以是0或1。“最低有效位”在左边(不是在右边)。 示例:1000001111 代表(十进制)数字 961,或 011101
我有来自实验的Base64 编码数据。所以我想逐步做的是: 从 base64 编码中检索字节(解码) 将字节转换为小端 从 (zlib) 中解压字节 字节数组转 float 组 示例: Dn3LQ3n
关闭。这个问题需要多问focused 。目前不接受答案。 想要改进此问题吗?更新问题,使其仅关注一个问题 editing this post . 已关闭 7 年前。 Improve this ques
解码字节时,binary.Read()要求您指定该操作的预期字节顺序。 binary.Read() 还允许您传入结构,但据我所知,它使用相同的字节顺序将字节流解码到结构中的每个字段中。 当编码整数的字
我将 24 位单声道音频 .wav 文件读入 > 7) * 255 data = a.view('
我正在解码一个二进制文件,它有用四个字节表示的十进制数字,小端。例如,94 53 F0 40代表 7.510202。不幸的是,Python 给了我 7.51020240784。 当我尝试使用 unpa
这种传输语法中的数据是如何组织的?来自标准的描述: This Transfer Syntax applies to the encoding of the entire DICOM Data Set.
我是一名优秀的程序员,十分优秀!