相关疑难解决方法(0)

用于测试Collat​​z猜想的C++代码比手写程序集更快 - 为什么?

我为Project Euler Q14编写了这两个解决方案,在汇编和C++中.它们是用于测试Collat​​z猜想的相同蛮力方法.装配解决方案与组装

nasm -felf64 p14.asm && gcc p14.o -o p14
Run Code Online (Sandbox Code Playgroud)

C++是用.编译的

g++ p14.cpp -o p14
Run Code Online (Sandbox Code Playgroud)

部件, p14.asm

section .data
    fmt db "%d", 10, 0

global main
extern printf

section .text

main:
    mov rcx, 1000000
    xor rdi, rdi        ; max i
    xor rsi, rsi        ; i

l1:
    dec rcx
    xor r10, r10        ; count
    mov rax, rcx

l2:
    test rax, 1
    jpe even

    mov rbx, 3
    mul rbx
    inc rax
    jmp c1

even:
    mov rbx, 2 …
Run Code Online (Sandbox Code Playgroud)

c++ optimization performance x86 assembly

803
推荐指数
8
解决办法
14万
查看次数

取消优化英特尔Sandybridge系列CPU中管道的程序

我一直在绞尽脑汁想要完成这项任务一周,我希望有人能带领我走向正确的道路.让我从教师的指示开始:

您的作业与我们的第一个实验作业相反,即优化素数计划.你在这个任务中的目的是使程序失望,即让它运行得更慢.这两个都是CPU密集型程序.他们需要几秒钟才能在我们的实验室电脑上运行.您可能无法更改算法.

要取消优化程序,请使用您对英特尔i7管道如何运行的了解.想象一下重新排序指令路径以引入WAR,RAW和其他危险的方法.想一想最小化缓存有效性的方法.恶魔无能.

该作业选择了Whetstone或Monte-Carlo程序.缓存有效性评论大多只适用于Whetstone,但我选择了Monte-Carlo模拟程序:

// Un-modified baseline for pessimization, as given in the assignment
#include <algorithm>    // Needed for the "max" function
#include <cmath>
#include <iostream>

// A simple implementation of the Box-Muller algorithm, used to generate
// gaussian random numbers - necessary for the Monte Carlo method below
// Note that C++11 actually provides std::normal_distribution<> in 
// the <random> library, which can be used instead of this function
double gaussian_box_muller() {
  double x = 0.0;
  double y = 0.0; …
Run Code Online (Sandbox Code Playgroud)

c++ optimization x86 intel cpu-architecture

313
推荐指数
4
解决办法
4万
查看次数

每个程序员应该了解的内存?

我想知道Ulrich Drepper 从2007年开始对每个程序员应该知道的内容有多少仍然有效.另外,我找不到比1.0更新的版本或勘误表.

optimization x86 memory-management cpu-architecture micro-optimization

145
推荐指数
3
解决办法
2万
查看次数

什么时候,如果循环展开仍然有用?

我一直试图通过循环展开来优化一些极其性能关键的代码(一种快速排序算法,在蒙特卡罗模拟中被称为数百万次).这是我试图加速的内循环:

// Search for elements to swap.
while(myArray[++index1] < pivot) {}
while(pivot < myArray[--index2]) {}
Run Code Online (Sandbox Code Playgroud)

我尝试展开类似的东西:

while(true) {
    if(myArray[++index1] < pivot) break;
    if(myArray[++index1] < pivot) break;
    // More unrolling
}


while(true) {
    if(pivot < myArray[--index2]) break;
    if(pivot < myArray[--index2]) break;
    // More unrolling
}
Run Code Online (Sandbox Code Playgroud)

这完全没有区别所以我把它改成了更易读的形式.我曾经尝试过循环展开,但我有类似的经历.鉴于现代硬件上的分支预测器的质量,何时(如果有的话)循环展开仍然是一个有用的优化?

language-agnostic optimization performance micro-optimization

88
推荐指数
3
解决办法
4万
查看次数

为什么英特尔在其处理器中隐藏内部RISC内核?

从Pentium Pro(P6微体系结构)开始,英特尔重新设计了它的微处理器,并在旧的CISC指令下使用了内部RISC内核.由于Pentium Pro所有CISC指令都分为较小的部分(uops),然后由RISC内核执行.

一开始我很清楚英特尔决定隐藏新的内部架构并强迫程序员使用"CISC shell".由于这一决定,英特尔可以在不破坏兼容性的情况下完全重新设计微处理器架构,这是合理的.

但是我不明白一件事,为什么英特尔仍然保留了多年内隐藏的内部RISC指令集?为什么他们不让程序员使用RISC指令,比如使用旧的x86 CISC指令集?

如果英特尔长期保持向后兼容性(我们仍然在64位模式旁边有虚拟8086模式),为什么它们不允许我们编译程序以便它们绕过CISC指令并直接使用RISC核心?这将开启自然的方式来慢慢放弃x86指令集,现在已弃用(这是英特尔决定在内部使用RISC核心的主要原因,对吧?).

看看新的英特尔'酷睿i'系列,我看到,他们只扩展了CISC指令集,增加了AVX,SSE4等.

x86 intel cpu-architecture

85
推荐指数
5
解决办法
4万
查看次数

在x86汇编中寄存器上使用的push/pop指令的功能是什么?

在阅读有关汇编程序的文章时,我经常遇到人们在写文件时他们推送处理器的某个寄存器并稍后再次弹出它以恢复它之前的状态.

  • 怎么能推一个寄存器?它在哪里推?为什么需要这个?
  • 这可归结为单处理器指令还是更复杂?

x86 assembly stack terminology

79
推荐指数
5
解决办法
26万
查看次数

编译32位和64位时,性能差异很大(快26倍)

我试图衡量在访问值类型和引用类型列表时使用a for和a 的区别foreach.

我使用以下类进行分析.

public static class Benchmarker
{
    public static void Profile(string description, int iterations, Action func)
    {
        Console.Write(description);

        // Warm up
        func();

        Stopwatch watch = new Stopwatch();

        // Clean up
        GC.Collect();
        GC.WaitForPendingFinalizers();
        GC.Collect();

        watch.Start();
        for (int i = 0; i < iterations; i++)
        {
            func();
        }
        watch.Stop();

        Console.WriteLine(" average time: {0} ms", watch.Elapsed.TotalMilliseconds / iterations);
    }
}
Run Code Online (Sandbox Code Playgroud)

我用double我的价值类型.我创建了这个'假类'来测试引用类型:

class DoubleWrapper
{
    public double Value { get; set; }

    public DoubleWrapper(double value)
    {
        Value …
Run Code Online (Sandbox Code Playgroud)

c# performance 32bit-64bit

78
推荐指数
2
解决办法
6303
查看次数

在L1缓存中获取Haswell的峰值带宽:仅获得62%

我试图在L1缓存中获得全部带宽,以便在Intel处理器上实现以下功能

float triad(float *x, float *y, float *z, const int n) {
    float k = 3.14159f;
    for(int i=0; i<n; i++) {
        z[i] = x[i] + k*y[i];
    }
}
Run Code Online (Sandbox Code Playgroud)

这是STREAM的三合一功能.

使用具有此功能的SandyBridge/IvyBridge处理器可获得约95%的峰值(使用NASM组装).但是,除非我展开循环,否则使用Haswell I仅达到峰值的62%.如果我展开16次,我得到92%.我不明白这一点.

我决定使用NASM在汇编中编写我的函数.装配中的主循环看起来像这样.

.L2:
    vmovaps         ymm1, [rdi+rax]
    vfmadd231ps     ymm1, ymm2, [rsi+rax]
    vmovaps         [rdx+rax], ymm1
    add             rax, 32
    jne             .L2
Run Code Online (Sandbox Code Playgroud)

在示例12.7-12.11 中的Agner Fog的优化组装手册中,他y[i] = y[i] +k*x[i]对Pentium M,Core 2,Sandy Bridge,FMA4和FMA3 做了几乎相同的事情(但是).我设法或多或少地自己重现了他的代码(实际上他在广播时在FMA3示例中有一个小错误).除FMA4和FMA3外,他为每个处理器的表格提供指令大小计数,融合操作,执行端口.我曾试图为FMA3制作这张桌子.

                                 ports
             size   ?ops-fused   0   1   2   3   4   5   6   7    
vmovaps      5      1                    ½   ½ …
Run Code Online (Sandbox Code Playgroud)

c memory assembly nasm fma

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

在x86上做水平浮点矢量和的最快方法

你有一个三(或四)个浮点数的向量.总结它们的最快方法是什么?

SSE(movaps,shuffle,add,movd)总是比x87快吗?SSE4.2中的水平加法说明值得吗?移动到FPU的成本是多少,然后是faddp,faddp?什么是最快的特定指令序列?

"尝试安排事情,这样你可以一次总结四个向量"将不被接受作为答案.:-)

floating-point optimization x86 assembly sse

41
推荐指数
4
解决办法
2万
查看次数

无用的测试指令?

我得到了下面的汇编列表作为我的java程序的JIT编译的结果.

mov    0x14(%rsp),%r10d
inc    %r10d              

mov    0x1c(%rsp),%r8d
inc    %r8d               

test   %eax,(%r11)         ; <--- this instruction

mov    (%rsp),%r9
mov    0x40(%rsp),%r14d
mov    0x18(%rsp),%r11d
mov    %ebp,%r13d
mov    0x8(%rsp),%rbx
mov    0x20(%rsp),%rbp
mov    0x10(%rsp),%ecx
mov    0x28(%rsp),%rax    

movzbl 0x18(%r9),%edi     
movslq %r8d,%rsi          

cmp    0x30(%rsp),%rsi
jge    0x00007fd3d27c4f17 
Run Code Online (Sandbox Code Playgroud)

我对这test条指令的理解在这里没用,因为测试的主要思想是

标志SF,ZF,PF被修改,而AND的结果被丢弃.

这里我们不使用这些结果标志.

这是JIT中的错误还是我错过了什么?如果是,报告的最佳位置在哪里?谢谢!

java assembly jit jvm jvm-hotspot

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