相关疑难解决方法(0)

最后的性能优化策略

这个网站上已经存在很多性能问题,但是我发现几乎所有这些都是特定于问题且相当狭窄的问题.几乎所有人都重复这些建议,以避免过早优化.

我们假设:

  • 代码已经正常工作
  • 所选择的算法对于问题的情况已经是最佳的
  • 已经测量了代码,并且已经隔离了违规的例程
  • 所有优化尝试也将被测量,以确保它们不会使事情变得更糟

我在这里寻找的是在一个关键算法中挤出最后几个百分点的策略和技巧,除此之外别无他法.

理想情况下,尝试使答案语言不可知,并在适用的情况下指出建议策略的任何缺点.

我将使用我自己的初步建议添加回复,并期待Stack Overflow社区可以想到的任何其他内容.

language-agnostic optimization performance

600
推荐指数
28
解决办法
8万
查看次数

为什么编译器不将浮点*2优化为指数增量?

我经常注意到gcc将乘法转换为可执行文件中的移位.当乘以a int和a 时,可能会发生类似的事情float.例如,2 * f可能只是将指数递增f1,从而节省了一些周期.编译器,也许是一个人请求他们这样做(例如通过-ffast-math),一般来说,这样做吗?

编译器通常是否足够聪明,或者我是否需要使用scalb*()ldexp()/frexp()函数系列自己完成此操作?

c c++ optimization performance compiler-optimization

46
推荐指数
4
解决办法
3844
查看次数

优化快速乘法但缓慢添加:FMA和doubledouble

当我第一次使用Haswell处理器时,我尝试使用FMA来确定Mandelbrot集.主要算法是这样的:

intn = 0;
for(int32_t i=0; i<maxiter; i++) {
    floatn x2 = square(x), y2 = square(y); //square(x) = x*x
    floatn r2 = x2 + y2;
    booln mask = r2<cut; //booln is in the float domain non integer domain
    if(!horizontal_or(mask)) break; //_mm256_testz_pd(mask)
    n -= mask
    floatn t = x*y; mul2(t); //mul2(t): t*=2
    x = x2 - y2 + cx;
    y = t + cy;
}
Run Code Online (Sandbox Code Playgroud)

这确定n像素是否在Mandelbrot集中.因此对于双浮点,它运行超过4个像素(floatn = __m256d,intn = __m256i).这需要4个SIMD浮点乘法和4个SIMD浮点加法.

然后我修改了这个就像这样使用FMA

intn n = 0; …
Run Code Online (Sandbox Code Playgroud)

floating-point x86 assembly mandelbrot fma

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

C内存分配器和严格别名

即使在阅读了相当多的严格别名规则后,我仍然感到困惑.据我所知,不可能实现遵循这些规则的合理的内存分配器,因为malloc永远不能重用释放的内存,因为内存可以用于在每次分配时存储不同的类型.

显然这不可能是正确的.我错过了什么?如何实现遵循严格别名的分配器(或内存池)?

谢谢.

编辑:让我用一个愚蠢的简单例子来澄清我的问题:

// s == 0 frees the pool
void *my_custom_allocator(size_t s) {
    static void *pool = malloc(1000);
    static int in_use = FALSE;
    if( in_use || s > 1000 ) return NULL;
    if( s == 0 ) {
        in_use = FALSE;
        return NULL;
    }
    in_use = TRUE;
    return pool;
}

main() {
    int *i = my_custom_allocator(sizeof(int));
    //use int
    my_custom_allocator(0);
    float *f = my_custom_allocator(sizeof(float)); //not allowed...
}
Run Code Online (Sandbox Code Playgroud)

c memory-management strict-aliasing language-lawyer

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

ldexp的目的是什么?

我想知道人们在实际应用中使用函数ldexp()是什么.

这是描述:

返回将x(有效数字)乘以2乘以exp(指数)的幂的结果.

c++

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

为什么 GCC 和 Clang 不使用指数的浮点到整数 PADDD 来优化乘以 2^n 的乘法,即使使用 -ffast-math 也是如此?

考虑到这个功能,

float mulHalf(float x) {
    return x * 0.5f;
}
Run Code Online (Sandbox Code Playgroud)

以下函数与正常输入/输出产生相同的结果。

float mulHalf_opt(float x) {
    __m128i e = _mm_set1_epi32(-1 << 23);
    __asm__ ("paddd\t%0, %1" : "+x"(x) : "xm"(e));
    return x;
}
Run Code Online (Sandbox Code Playgroud)

这是带有 的汇编输出-O3 -ffast-math

mulHalf:
        mulss   xmm0, DWORD PTR .LC0[rip]
        ret

mulHalf_opt:
        paddd   xmm0, XMMWORD PTR .LC1[rip]
        ret
Run Code Online (Sandbox Code Playgroud)

-ffast-math启用-ffinite-math-only“假设参数和结果不是 NaN 或 +-Infs” [1]

因此,如果在 的容差下生成更快的代码,则的编译输出可能会更好地与onmulHalf一起使用。paddd-ffast-math-ffast-math

我从Intel Intrinsics Guide中获得了下表。

(MULSS)
Architecture    Latency Throughput (CPI)
Skylake         4       0.5 …
Run Code Online (Sandbox Code Playgroud)

c floating-point x86 assembly compiler-optimization

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