我需要按照下面的模式加载并重新排列12个字节到16(或24到32):
ABC DEF GHI JKL
Run Code Online (Sandbox Code Playgroud)
变
ABBC DEEF GHHI JKKL
Run Code Online (Sandbox Code Playgroud)
您能否建议使用SSE(2)和/或AVX(2)指令实现此目的的有效方法?
这需要重复执行,因此允许预先存储的掩码或常量.
我尝试与SSE合作,但遇到了一些奇怪的行为。
我编写了简单的代码,用于将两个字符串与SSE Intrinsics进行比较,然后运行它并起作用。但是后来我明白了,在我的代码中,指针之一仍然没有对齐,但是我使用了_mm_load_si128指令,它要求指针在16字节边界上对齐。
//Compare two different, not overlapping piece of memory
__attribute((target("avx"))) int is_equal(const void* src_1, const void* src_2, size_t size)
{
//Skip tail for right alignment of pointer [head_1]
const char* head_1 = (const char*)src_1;
const char* head_2 = (const char*)src_2;
size_t tail_n = 0;
while (((uintptr_t)head_1 % 16) != 0 && tail_n < size)
{
if (*head_1 != *head_2)
return 0;
head_1++, head_2++, tail_n++;
}
//Vectorized part: check equality of memory with SSE4.1 instructions
//src1 - …Run Code Online (Sandbox Code Playgroud) 我有一个功能可以将 8 位图像缩小两倍。我之前已经用 SSE 优化了 rgb32 案例。现在我想对 gray8 案例做同样的事情。
在核心,有一个函数取两行像素数据,其工作方式如下:
/**
* Calculates the average of two rows of gray8 pixels by averaging four pixels.
*/
void average2Rows(const uint8_t* row1, const uint8_t* row2, uint8_t* dst, int size)
{
for (int i = 0; i < size - 1; i += 2)
*(dst++) = ((row1[i]+row1[i+1]+row2[i]+row2[i+1])/4)&0xFF;
}
Run Code Online (Sandbox Code Playgroud)
现在,我想出了一个 SSE 变体,它大约快三倍,但它确实涉及很多改组,我认为可能会做得更好。有人看到这里可以优化什么吗?
/* row1: 16 8-bit values A-P
* row2: 16 8-bit values a-p
* returns 16 8-bit values (A+B+a+b)/4, (C+D+c+d)/4, ..., …Run Code Online (Sandbox Code Playgroud) 为了提供一些背景知识,我想研究x86指令是如何手动编码/解码的。我遇到了ModR/Mand SIB字节,似乎了解x86寻址模式对于理解指令编码方案至关重要。
因此,我在Google搜索了x86寻址模式。搜索返回的大多数博客/视频都是8086处理器的寻址模式。通过其中的一些,不同的寻址模式是寄存器,直接,间接,索引,基于等。但是,在引用这些寻址方式时,博客使用的名称不一致。多个不同的源使用多种不同的寻址模式。此处的英特尔手册中甚至没有提到这些不同的术语。例如,我似乎无法在Intel手册中找到任何称为“直接”或“间接”的寻址模式。另外,Mod在比特ModRM字节是一个2比特字段,这使我不知道是否超过4种的寻址方式是可能的。
我的问题是,诸如直接寻址模式之类的术语是间接寻址模式的旧术语,这些术语不再在英特尔手册中使用,而是由公众使用。如果存在技术上确实存在的术语,则可以在手册中找到它们的引用。
我的原始数据是一堆c数组(长度为1000000)(无符号)char(8位)。我想将它们加在一起(矢量加法),遵循以下代码中的规则。结果:(无符号)short(16位)的c数组。
我已经阅读了所有SSE和AVX / AVX2,但有一个类似的调用,即多个2个256位寄存器。前4个32位将相乘,每对32位的结果是一个64位,将适合256个寄存器。(_mm256_mul_epi32,_mm256_mul_epu32)
https://www.codeproject.com/Articles/874396/Crunching-Numbers-with-AVX-and-AVX
样例代码:
static inline void adder(uint16_t *canvas, uint8_t *addon, uint64_t count)
{
for (uint64_t i=0; i<count; i++)
canvas[i] += static_cast<uint16_t>(addon[i]);
}
Run Code Online (Sandbox Code Playgroud)
谢谢
因此,此插入排序是用x86编写的,但嵌入在C中。它还具有一个标志,在对数组的一半进行排序后,我们将其设置为保留。有什么办法可以提高性能?
void asmInsSort(int *list, int arrayLen, int halfpoint) {
_asm
{
mov ecx, arrayLen
mov esi, list
mov ebx, halfpoint
mov eax, 0
more:
cmp ecx, 0 // Compare current arrayLen w/ 0
je done // If it is equal, we are done
mov edi, eax //J = I
push eax //push eax (i) to free up register for key
mov eax, [esi + edi] //Key = Array[i] technically j
sub edi, 4 //J - 1
mov edx, arrayLen //K …Run Code Online (Sandbox Code Playgroud) x86 assembly inline-assembly micro-optimization insertion-sort
这是我在 AVX512BW 中的“strlen”函数的代码
vxorps zmm0, zmm0, zmm0 ; ZMM0 = 0
vpcmpeqb k0, zmm0, [ebx] ; ebx is string and it's aligned at 64-byte boundary
kortestq k0, k0 ; 0x00 found ?
jnz .chk_0x00
Run Code Online (Sandbox Code Playgroud)
现在对于'chk_0x00',在x86_64系统中,没有问题,我们可以这样处理:
chk_0x00:
kmovq rbx, k0
tzcnt rbx, rbx
add rax, rbx
Run Code Online (Sandbox Code Playgroud)
这里我们有一个 64 位寄存器,因此我们可以将掩码存储到其中,但我的问题是关于 x86 系统,我们没有任何 64 位寄存器,因此我们必须使用“内存”保留(8 字节)并检查两者掩码的DWORD一一对应(其实这是我的方式,我想知道有没有更好的方式)
chk_0x00:
kmovd ebx, k0 ; move the first dword of the mask to the ebx
test ebx, ebx ; 0x00 found in the first dword ?
jz …Run Code Online (Sandbox Code Playgroud) 所以,我有3个参数的汇编程序ASM_Method(void*, void*, int)和init_method(float, int*).感兴趣的是前者的无效指针.
当我从C++文件中调用方法时,参数为:
float src[64];
float dest[64];
int radius[3];
init_method(1.5, radius);
ASM_Method(src, dest, 64);
Run Code Online (Sandbox Code Playgroud)
反汇编这个调用过程:
mov r8d,100h
lea rdx,[rbp+0A0h]
lea rcx,[rbp-60h]
call ASM_Method
Run Code Online (Sandbox Code Playgroud)
是否已初始化,程序运行正常.但是,当我这样做时:
float* src = new float[64];
float* dest = new float[64];
int radius[3];
init_method(1.5, radius);
ASM_Method(src, dest, 64);
Run Code Online (Sandbox Code Playgroud)
调用时,RCX设置为非正确地址的值,但RDX是正确的.程序崩溃了.
反汇编这个调用过程:
mov r8d,100h
mov rdx,rbx
mov rcx,rdi
call ASM_Method
Run Code Online (Sandbox Code Playgroud)
除非我将src初始化为某些值,否则RCX在调用时会更改为无效地址(在本例中为1).
ASM_Method的汇编代码:
mov rax, rdx
add rax, r8
shr r8, 4
inc r8
xor r9, r9
movdqu xmm1, [rax]
MainLoop:
movdqu xmm0, [rcx …Run Code Online (Sandbox Code Playgroud) NASM 可以在 64 位系统(Windows 7)上分配多少内存?fasm 似乎只能分配大约 1.5 GB 的内存,所以我正在寻找更强大的汇编程序。
我使用以下perf命令对用户空间对 DRAM 的读取访问进行采样evince:
perf record -d --call-graph dwarf -c 100 -e mem_load_uops_retired.l3_miss:uppp /opt/evince-3.28.4/bin/evince
Run Code Online (Sandbox Code Playgroud)
可以看出,我使用该PEBS功能来提高采样的准确性。但是有一些非内存访问报告为内存访问。例如,这是一个由 报告的采样事件perf script:
evince 20589 16079.401401: 100 mem_load_uops_retired.l3_miss:uppp: 555555860750 5080022 N/A|SNP N/A|TLB N/A|LCK N/A
555555579939 ev_history_can_go_back+0x19 (/opt/evince-3.28.4/bin/evince)
5555555862ef ev_window_update_actions_sensitivity+0xa1f (/opt/evince-3.28.4/bin/evince)
55555558ce4f ev_window_page_changed_cb+0xf (/opt/evince-3.28.4/bin/evince)
7ffff574510c g_closure_invoke+0x19c (/usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.5600.4)
7ffff575805d signal_emit_unlocked_R+0xf4d (/usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.5600.4)
7ffff5760714 g_signal_emit_valist+0xa74 (/usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.5600.4)
7ffff576112e g_signal_emit+0x8e (/usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.5600.4)
7ffff7140d76 emit_value_changed+0xf6 (inlined)
7ffff7140d76 adjustment_set_value+0xf6 (inlined)
7ffff7140d76 gtk_adjustment_set_value_internal+0xf6 (/usr/lib/x86_64-linux-gnu/libgtk-3.so.0.2200.30)
7ffff574510c g_closure_invoke+0x19c (/usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.5600.4)
7ffff5757de7 signal_emit_unlocked_R+0xcd7 (/usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.5600.4)
7ffff575fc7f g_signal_emitv+0x27f (/usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.5600.4)
7ffff7153519 gtk_binding_entry_activate+0x289 (/usr/lib/x86_64-linux-gnu/libgtk-3.so.0.2200.30)
7ffff71539ef binding_activate+0x5f (/usr/lib/x86_64-linux-gnu/libgtk-3.so.0.2200.30) …Run Code Online (Sandbox Code Playgroud)