标签: x86-64

如何在Visual Studio 2010中添加x64(或任何CPU)作为构建选项(从控制台应用程序到类库)

最初,我使用Mass Transit作为我的服务总线创建了一个控制台应用程序.最近,我切换到NServiceBus,它不需要你创建一个控制台应用程序,而是一个类库.在项目属性中,我只是将将其更改的设置从控制台应用程序切换到库,但是只能为x86构建它的约束仍然有效.

我现在无法将构建类型更改为任何CPU,因为它是一个控制台应用程序,现在应该是有效的.有没有办法将我的应用程序完全更改为类库,以便我可以运行构建任何CPU选项?我是否需要创建一个新项目,将文件复制到其中并继续这样做?或者它是否像改变项目(.proj)文件中的内容一样简单?

堆栈溢出问题缺少调试|任何项目的CPU构建配置和默认为Windows x64上的Debug | x86仅为控制台应用程序提供了有关此x86问题的更多上下文.

projects-and-solutions x86-64 visual-studio-2010 anycpu

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

预取数据以缓存x86-64

在我的应用程序中,我需要在一个大的连续内存数据块(100个MB)上执行计算.我想的是继续预取我的程序将来会触及的块的部分,这样当我对该部分执行计算时,数据已经在缓存中.

有人能给我一个简单的例子来说明如何用gcc实现这个目标吗?我在_mm_prefetch某处读过,但不知道如何正确使用它.另请注意,我有一个多核系统,但每个核心将并行处理不同的内存区域.

c linux caching x86-64 prefetch

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

Linux:大型int数组:mmap vs seek文件?

假设我有一个数据集,它是一个1e12 32位整数(4 TB)的数组,存储在4TB HDD ext4文件系统的文件中.

考虑到数据很可能是随机的(或者至少是随机的).

// pseudo-code
for (long long i = 0; i < (1LL << 40); i++)
   SetFileIntAt(i) = GetRandInt();
Run Code Online (Sandbox Code Playgroud)

此外,考虑到我希望以不可预测的顺序读取单个int元素,并且该算法无限运行(它正在进行中).

// pseudo-code
while (true)
   UseInt(GetFileInt(GetRand(1<<40)));
Run Code Online (Sandbox Code Playgroud)

我们在Linux x86_64,gcc上.您可以假设系统有4GB的RAM(即比数据集少1000x)

以下是架构访问的两种方法:

(A)将文件mmap到4TB内存块,并将其作为int数组访问

(B)打开(2)文件并使用seek(2)和read(2)来读取整数.

A和B中哪个会有更好的性能?为什么?

是否有其他设计可以提供比A或B更好的性能?

linux memory filesystems memory-management x86-64

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

为什么不在XMM向量寄存器中存储函数参数?

我正在阅读这本书:"计算机系统 - 程序员视角".我发现,在x86-64架构中,我们仅限于6个积分参数,这些参数将被传递给寄存器中的函数.下一个参数将在堆栈上传递.

而且,第一个最多8个FP或矢量args以xmm0..7传递.

为什么不使用浮点寄存器来存储下一个参数,即使参数不是单/双精度变量?

将数据存储在寄存器中比将其存储到存储器然后从存储器中读取它会更有效(据我所知).

x86 assembly x86-64 parameter-passing calling-convention

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

编译器:了解从小程序生成的汇编代码

我正在自学,编译器是如何工作的.我正在学习从小型64位Linux程序中读取GCC生成代码的反汇编.

我写了这个C程序:

#include <stdio.h>

int main()
{
    for(int i=0;i<10;i++){
        int k=0;
    }
}
Run Code Online (Sandbox Code Playgroud)

使用objdump之后我得到:

00000000004004d6 <main>:
  4004d6:       55                      push   rbp
  4004d7:       48 89 e5                mov    rbp,rsp
  4004da:       c7 45 f8 00 00 00 00    mov    DWORD PTR [rbp-0x8],0x0
  4004e1:       eb 0b                   jmp    4004ee <main+0x18>
  4004e3:       c7 45 fc 00 00 00 00    mov    DWORD PTR [rbp-0x4],0x0
  4004ea:       83 45 f8 01             add    DWORD PTR [rbp-0x8],0x1
  4004ee:       83 7d f8 09             cmp    DWORD PTR [rbp-0x8],0x9
  4004f2:       7e …
Run Code Online (Sandbox Code Playgroud)

c linux gcc x86-64 disassembly

15
推荐指数
3
解决办法
1859
查看次数

对齐AVX-256内存存储是否值得打扰?

根据英特尔®64和IA-32架构优化参考手册 B.4节("英特尔®微体系架构代码名称Sandy Bridge的性能调整技术"),B.4.5.2小节("协助"):

跨越两页的32字节AVX存储指令需要一个大约150个周期的辅助.

我正在使用YMM寄存器来复制小型固定大小的内存块,从32到128个字节,并且这些块在堆管理器中以16个字节对齐.该堆管理器之前使用过XMM寄存器movdqa,我想将其"升级"为YMM,而不将对齐从16字节更改为32字节.所以我正在使用vmovdqu ymm0, ymmword ptr [rcx],vmovdqu ymmword ptr [rdx], ymm0等等......

如果我正确理解了英特尔文档的页面大小,如果我在4K页面边界上进行32字节存储,那么我将获得150个周期的惩罚.

但由于这些块已经对齐了16个字节,因此我点击跨页面存储的可能性是16/4096 = 1/256.如果我们在统计上推断出,在每个32字节的存储上,我在Sandy Bridge上得到1/255*150(= 0.5859375)个周期惩罚.

这不是那么多,并且由于将对齐从16字节更改为32字节,因此检查对齐或内存浪费肯定比分支更便宜.

我有以下问题:

  1. 我的计算是否正确?

  2. 对齐AVX-256内存存储器是否值得为小型固定大小的内存复制例程(32-128字节)而烦恼,因为达到惩罚的可能性如此之低?

  3. 是否存在比Sandy Bridge更高的未对齐32字节存储损失的处理器 - 例如,AMD或其他英特尔微体系结构?

memory assembly x86-64 avx avx2

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

什么是_mm_prefetch()位置提示?

内部函数导说,只有这么多关于void _mm_prefetch (char const* p, int i):

从包含地址p的内存中获取数据行到由locality hint i指定的缓存层次结构中的位置.

你能列出int i参数的可能值并解释它们的含义吗?

我发现_MM_HINT_T0,_MM_HINT_T1,_MM_HINT_T2,_MM_HINT_NTA_MM_HINT_ENTA,但我不知道这是否是一个详尽的列表和它们的含义.

如果特定于处理器,我想知道他们在Ryzen和最新的英特尔酷睿处理器上做了什么.

c++ x86-64 prefetch intrinsics cpu-cache

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

为什么typeA == typeB比typeA == typeof(TypeB)慢?

我最近一直在优化/基准测试一些代码,并遇到了这种方法:

public void SomeMethod(Type messageType)
{
    if (messageType == typeof(BroadcastMessage))
    {
        // ...
    }
    else if (messageType == typeof(DirectMessage))
    {
        // ...
    }
    else if (messageType == typeof(ClientListRequest))
    {
        // ...
    }
}
Run Code Online (Sandbox Code Playgroud)

这是从其他地方的性能关键循环typeof(...)调用的,因此我自然地假设所有这些调用都增加了不必要的开销(我知道微优化)并且可以移动到类中的私有字段.(我知道有更好的方法来重构这些代码,但是,我仍然想知道这里发生了什么.)

根据我的基准测试,情况并非如此(使用BenchmarkDotNet).

[DisassemblyDiagnoser(printAsm: true, printSource: true)]
[RyuJitX64Job]
public class Tests
{
    private Type a = typeof(string);
    private Type b = typeof(int);

    [Benchmark]
    public bool F1()
    {
        return a == typeof(int);
    }

    [Benchmark]
    public bool F2()
    {
        return a == b;
    }
}
Run Code Online (Sandbox Code Playgroud)

在我的机器上的结果(Window …

.net c# assembly x86-64

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

为什么编译器坚持在这里使用被调用者保存的寄存器?

考虑这个 C 代码:

void foo(void);

long bar(long x) {
    foo();
    return x;
}
Run Code Online (Sandbox Code Playgroud)

当我在 GCC 9.3 上使用-O3或编译它时-Os,我得到这个:

bar:
        push    r12
        mov     r12, rdi
        call    foo
        mov     rax, r12
        pop     r12
        ret
Run Code Online (Sandbox Code Playgroud)

除了选择rbx而不是r12作为被调用者保存的寄存器之外,clang 的输出是相同的。

但是,我希望/期望看到看起来更像这样的程序集:

bar:
        push    rdi
        call    foo
        pop     rax
        ret
Run Code Online (Sandbox Code Playgroud)

由于无论如何您都必须将某些内容推送到堆栈中,因此将您的值推送到那里似乎更短,更简单,并且可能更快,而不是将一些任意的被调用者保存的寄存器值推送到那里,然后将您的值存储在该寄存器中。call foo当你把东西放回去后,反之亦然。

我的组装错了吗?它在某种程度上比弄乱额外的寄存器效率低吗?如果这两个的答案都是“否”,那么为什么 GCC 或 clang 不这样做呢?

Godbolt 链接


编辑:这是一个不太简单的例子,即使变量被有意义地使用,它也会发生:

long foo(long);

long bar(long x) {
    return foo(x * x) - x;
}
Run Code Online (Sandbox Code Playgroud)

我明白了:

bar:
        push    rbx …
Run Code Online (Sandbox Code Playgroud)

c assembly gcc x86-64 register-allocation

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

为什么这个函数在额外读取内存时运行得如此之快?

我目前正在尝试了解 x86_64(特别是我的 Intel(R) Core(TM) i3-8145U CPU @ 2.10GHz 处理器)上某些循环的性能属性。具体来说,在循环体内部添加一个额外的读取内存指令几乎可以使性能翻倍,而细节并不是特别重要。

我一直在使用一个测试程序,它由两个主要部分组成:一个测试循环和一个被测函数。测试循环运行被测函数 2 32次,一次将每个有符号的 32 位整数作为参数(按从INT_MIN到 的顺序INT_MAX)。被测函数(名为body)是一个小函数,用于检查是否使用预期参数调用它,否则将错误记录在全局变量中。测试程序涉及的内存量足够小,所有东西都可能适合 L1 缓存。

为了消除可能由编译器行为引起的任何速度差异,我用汇编语言编写了两个有问题的函数(我clang用作汇编程序),并被迫从固定地址(这种测试循环的性能通常受与对齐或缓存相关的影响所支配,因此使用固定地址将消除任何与更改无关的对齐效果或缓存效果)。

这是反汇编的测试循环(它需要函数的地址在 中循环%rdi):

  401300:       53                      push   %rbx
  401301:       55                      push   %rbp
  401302:       51                      push   %rcx
  401303:       48 89 fd                mov    %rdi,%rbp
  401306:       bb 00 00 00 80          mov    $0x80000000,%ebx
loop:
  40130b:       89 df                   mov    %ebx,%edi
  40130d:       ff d5                   callq  *%rbp
  40130f:       83 c3 01                add    $0x1,%ebx
  401312:       71 f7                   jno    40130b <loop> …
Run Code Online (Sandbox Code Playgroud)

performance assembly x86-64 cpu-architecture clang

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