相关疑难解决方法(0)

SSE,内在函数和对齐

我使用了很多SSE编译器内在函数编写了一个3D矢量类.一切正常,直到我开始实现具有3D矢量作为新成员的类.我在发布模式下经历了奇怪的崩溃,但在调试模式下却没有,反之亦然.

所以我读了一些文章,并认为我需要将拥有3D矢量类实例的类对齐到16个字节.所以我只是在类之前添加了_MM_ALIGN16(__declspec(align(16)),如下所示:

_MM_ALIGN16 struct Sphere
{
    // ....

    Vector3 point;
    float radius
};
Run Code Online (Sandbox Code Playgroud)

这似乎首先解决了这个问题.但在更改了一些代码后,我的程序又开始以奇怪的方式崩溃.我在网上搜索了一些,发现了一篇博客文章.我尝试了作者Ernst Hot为解决这个问题做了什么,它对我也有用.我在我的类中添加了new和delete运算符,如下所示:

_MM_ALIGN16 struct Sphere
{
    // ....

    void *operator new (unsigned int size)
     { return _mm_malloc(size, 16); }

    void operator delete (void *p)
     { _mm_free(p); }

    Vector3 point;
    float radius
};
Run Code Online (Sandbox Code Playgroud)

恩斯特提到这种方法也可能存在问题,但他只是链接到一个不再存在的论坛,而没有解释为什么它可能会有问题.

所以我的问题是:

  1. 定义运算符有什么问题?

  2. 为什么不添加_MM_ALIGN16足够的类定义?

  3. 处理SSE内在函数的对齐问题的最佳方法是什么?

c++ sse alignment intrinsics

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

非临时负载和硬件预取器,它们一起工作吗?

当从连续的内存位置执行一系列_mm_stream_load_si128()调用(MOVNTDQA)时,硬件预取器是否仍会启动,或者我应该使用显式软件预取(使用NTA提示)以获得预取的好处,同时仍然避免缓存污染?

我问这个的原因是因为他们的目标似乎与我相矛盾.流加载将获取绕过缓存的数据,而预取器尝试主动将数据提取到缓存中.

当顺序迭代一个大型数据结构(处理过的数据不会在很长一段时间内被修饰)时,我有必要避免污染chache层次结构,但我不想因频繁出现频繁的~100次循环处罚-fetcher闲置.

目标架构是Intel SandyBridge

performance x86 sse prefetch cpu-cache

9
推荐指数
3
解决办法
2512
查看次数

对齐与未对齐的x86 SIMD指令之间的选择

通常有两种类型的SIMD指令:

A.使用对齐的内存地址的那些,如果地址未在操作数大小边界上对齐,则会引发一般保护(#GP)异常:

movaps  xmm0, xmmword ptr [rax]
vmovaps ymm0, ymmword ptr [rax]
vmovaps zmm0, zmmword ptr [rax]
Run Code Online (Sandbox Code Playgroud)

B.以及使用未对齐内存地址的那些,不会引发此类异常:

movups  xmm0, xmmword ptr [rax]
vmovups ymm0, ymmword ptr [rax]
vmovups zmm0, zmmword ptr [rax]
Run Code Online (Sandbox Code Playgroud)

但是我只是好奇,为什么我要用脚射击自己并使用第一组的对齐记忆指令呢?

x86 sse simd avx avx512

8
推荐指数
2
解决办法
755
查看次数

MSVC 生成不必要的复杂指令

在对涉及 的代码进行基准测试时std::optional<double>,我注意到 MSVC 生成的代码的运行速度大约是 clang 或 gcc 生成的代码的一半。在花了一些时间减少代码后,我注意到 MSVC 显然在为std::optional::operator=. 使用std::optional::emplace()不会表现出速度减慢。

以下功能

void test_assign(std::optional<double> & f){
    f = std::optional{42.0};
}
Run Code Online (Sandbox Code Playgroud)

产生

sub     rsp, 24
vmovsd  xmm0, QWORD PTR __real@4045000000000000
mov     BYTE PTR $T1[rsp+8], 1
vmovups xmm1, XMMWORD PTR $T1[rsp]
vmovsd  xmm1, xmm1, xmm0
vmovups XMMWORD PTR [rcx], xmm1
add     rsp, 24
ret     0
Run Code Online (Sandbox Code Playgroud)

注意未对齐的 mov 操作。相反,函数

void test_emplace(std::optional<double> & f){
    f.emplace(42.0);
}
Run Code Online (Sandbox Code Playgroud)

编译为

mov     rax, 4631107791820423168      ; 4045000000000000H
mov     BYTE PTR [rcx+8], 1
mov …
Run Code Online (Sandbox Code Playgroud)

c++ x86-64 compiler-optimization visual-c++ stdoptional

7
推荐指数
0
解决办法
218
查看次数

有没有办法强制 Visual Studio 从 SSE 内在函数生成对齐的指令?

_mm_load_ps() SSE 内在函数被定义为对齐的,如果地址未对齐则抛出异常。然而,视觉工作室似乎生成了未对齐的读取。

由于并非所有编译器都是相同的,这隐藏了错误。如果能够打开实际的对齐操作,那就太好了,尽管以前的性能影响似乎不再存在了。

换句话说,编写代码:

__m128 p1 = _mm_load_ps(data);
Run Code Online (Sandbox Code Playgroud)

目前生产:

movups      xmm0,xmmword ptr [eax]
Run Code Online (Sandbox Code Playgroud)

预期结果:

movaps      xmm0,xmmword ptr [eax]
Run Code Online (Sandbox Code Playgroud)

(我是被微软要求来这里问的)

sse memory-alignment intrinsics visual-studio visual-c++

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