相关疑难解决方法(0)

使用向量指令进行复杂的数据重组

我需要按照下面的模式加载并重新排列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)指令实现此目的的有效方法?

这需要重复执行,因此允许预先存储的掩码或常量.

x86 simd vectorization sse2 avx2

2
推荐指数
1
解决办法
304
查看次数

对齐和SSE异常行为

我尝试与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)

c c++ sse intel simd

2
推荐指数
1
解决办法
785
查看次数

使用 SSE 对 8 位灰度图像进行最快的缩小

我有一个功能可以将 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)

c++ x86 sse image-processing simd

2
推荐指数
1
解决办法
750
查看次数

Intel x86手册中是否确实存在像直接/间接寻址模式这样的术语?

为了提供一些背景知识,我想研究x86指令是如何手动编码/解码的。我遇到了ModR/Mand SIB字节,似乎了解x86寻址模式对于理解指令编码方案至关重要。

因此,我在Google搜索了x86寻址模式。搜索返回的大多数博客/视频都是8086处理器的寻址模式。通过其中的一些,不同的寻址模式是寄存器,直接,间接,索引,基于等。但是,在引用这些寻址方式时,博客使用的名称不一致。多个不同的源使用多种不同的寻址模式。此处的英特尔手册中甚至没有提到这些不同的术语。例如,我似乎无法在Intel手册中找到任何称为“直接”或“间接”的寻址模式。另外,Mod在比特ModRM字节是一个2比特字段,这使我不知道是否超过4种的寻址方式是可能的。

我的问题是,诸如直接寻址模式之类的术语是间接寻址模式的旧术语,这些术语不再在英特尔手册中使用,而是由公众使用。如果存在技术上确实存在的术语,则可以在手册中找到它们的引用。

x86 assembly addressing-mode

2
推荐指数
1
解决办法
738
查看次数

将大型char8的c数组转换为short16的最快方法是什么?

我的原始数据是一堆c数组(长度为1000000)(无符号)char(8位)。我想将它们加在一起(矢量加法),遵循以下代码中的规则。结果:(无符号)short(16位)的c数组。

我已经阅读了所有SSE和AVX / AVX2,但有一个类似的调用,即多个2个256位寄存器。前4个32位将相乘,每对32位的结果是一个64位,将适合256个寄存器。(_mm256_mul_epi32,_mm256_mul_epu32)

Firgure

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)

谢谢

c c++ intel intrinsics

2
推荐指数
1
解决办法
204
查看次数

如何加快这种插入排序?(C中的内联汇编)

因此,此插入排序是用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

2
推荐指数
1
解决办法
116
查看次数

AVX512BW:使用 bsf / tzcnt 处理 32 位代码中的 64 位掩码?

这是我在 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)

x86 assembly 32-bit micro-optimization avx512

2
推荐指数
1
解决办法
606
查看次数

在x86_64汇编中调用约定差异

所以,我有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)

assembly x86-64 masm calling-convention

1
推荐指数
1
解决办法
276
查看次数

NASM 可以分配多少内存?

NASM 可以在 64 位系统(Windows 7)上分配多少内存?fasm 似乎只能分配大约 1.5 GB 的内存,所以我正在寻找更强大的汇编程序。

assembly x86-64 nasm

1
推荐指数
1
解决办法
414
查看次数

Perf 将一些直接跳转指令报告为内存访问指令

我使用以下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)

linux x86-64 performancecounter memory-access perf

1
推荐指数
1
解决办法
79
查看次数