相关疑难解决方法(0)

为什么MSVS没有优化+0?

这个问题展示了一个非常有趣的现象:非规范化浮点数使代码减慢了一个数量级以上.

接受的答案中很好地解释了这种行为.但是,有一条评论,目前有48条评论,我找不到满意的答案:

为什么编译器在这种情况下不会降低+/- 0?- 迈克尔多根

旁注:我的印象是0f是/必须是完全可表示的(此外 - 它的二进制表示必须全为零),但在c11标准中找不到这样的声明.证明这一点的引用,或反驳这一主张的论点,将是最受欢迎的.无论如何,迈克尔的问题是这里的主要问题.


§5.2.4.2.2

实现可以给零和不是浮点数(例如无穷大和NaN)的值作为符号或者可以使它们保持未签名.

c floating-point

50
推荐指数
2
解决办法
2293
查看次数

编译器会简化一次顺序执行几次的操作吗?

我这个问题已经很久了,但是却不知道在哪里看。如果某个操作多次编写,编译器会简化它还是运行完全相同的操作并获得完全相同的答案?

例如,在下文(i%3)*10中,多次重复类似c的伪代码。

for(int i=0; i<100; i++) {
    array[(i%3)*10] = someFunction((i%3)*10);
    int otherVar = (i%3)*10 + array[(i%3)*10];
    int lastVar = (i%3)*10 - otherVar;
    anotherFunction(lastVar);
}
Run Code Online (Sandbox Code Playgroud)

我了解变量在视觉上会更好,但会更快吗?是(i%3)*10计算每循环5次?

在某些情况下,我不知道使用变量还是仅保留原始操作更快。

编辑:在胜利10上使用gcc(MinGW.org GCC-8.2.0-3)8.2.0

c c++ optimization

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

使用GCC进行SIMD(SSE/AVX)广播

我已经将我的大部分SIMD代码转换为GCC的向量扩展.但是,我没有找到一个很好的广播解决方案,如下所示

__m256 areg0 = _mm256_broadcast_ss(&a[i]);
Run Code Online (Sandbox Code Playgroud)

我想要做

__m256 argeg0 = a[i];
Run Code Online (Sandbox Code Playgroud)

如果你通过使用SSE常数看到我在Mutiplying向量的答案,我设法让广播与另一个SIMD寄存器一起工作.以下作品:

__m256 x,y;
y = x + 3.14159f; // broadcast x + 3.14159
y = 3.14159f*x;  // broadcast 3.14159*x
Run Code Online (Sandbox Code Playgroud)

但这不起作用:

 __m256 x;
 x = 3.14159f;  //should broadcast 3.14159 but does not work
Run Code Online (Sandbox Code Playgroud)

我怎样才能用GCC做到这一点?

gcc sse simd avx

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

GNU C本机向量:如何广播标量,如x86的_mm_set1_epi16

我如何编写一个可移植的GNU C内置向量版本,它不依赖于x86 set1内在函数?

typedef uint16_t v8su __attribute__((vector_size(16)));

v8su set1_u16_x86(uint16_t scalar) {
    return (v8su)_mm_set1_epi16(scalar);   // cast needed for gcc
}
Run Code Online (Sandbox Code Playgroud)

当然必须有一个更好的方式

v8su set1_u16(uint16_t s) {
    return (v8su){s,s,s,s,  s,s,s,s};
}
Run Code Online (Sandbox Code Playgroud)

我不想写一个用于广播单个字节的AVX2版本!

对于你想要分配给变量而不是仅仅使用二元运算符的操作数(这与gcc一起工作,见下文),即使只对gcc-only或clang-only这一部分的答案也会很有趣.


如果我想使用广播标量作为二元运算符的一个操作数,则可以使用gcc(如手册中所述),但不能使用clang:

v8su vecdiv10(v8su v) { return v / 10; }   // doesn't compile with clang
Run Code Online (Sandbox Code Playgroud)

有了clang,如果我只针对x86并且只使用本机向量语法来让编译器为我生成模数乘法逆常数和指令,我可以写:

v8su vecdiv_set1(v8su v) {
    return v / (v8su)_mm_set1_epi16(10);   // gcc needs the cast
}
Run Code Online (Sandbox Code Playgroud)

但是如果我加宽向量(to _mm256_set1_epi16),我必须改变内在,而不是通过改变到vector_size(32)一个地方(对于不需要改组的纯垂直SIMD )将整个代码转换为AVX2 .它也会破坏本机向量的部分目的,因为它不会为ARM或任何非x86目标编译.

丑陋的演员阵容是必需的,因为与clang不同,gcc不v8us {aka __vector(8) short …

c gcc simd clang intrinsics

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

在IEEE 754中,为什么在无操作中添加负零会产生但是添加正零则不会?

我在Rust中使用了一些算法(尽管这个语言对我的问题并不重要).考虑一下代码:

#[no_mangle]
pub fn test(x: f32) -> f32 {
    let m = 0.;
    x + m
}

fn main() {
    test(2.);
}
Run Code Online (Sandbox Code Playgroud)

它生成以下LLVM IR和相应的x86_64 asm(已启用优化):

;; LLVM IR
define float @test(float %x) unnamed_addr #0 {
start:
    %0 = fadd float %x, 0.000000e+00
    ret float %0
}

;; x86_64
; test:
    xorps xmm1, xmm1
    addss xmm0, xmm1
    ret
Run Code Online (Sandbox Code Playgroud)

如果我更改let m = 0.;let m = -0.;浮点,则添加优化:

;; LLVM IR
define float @test(float returned %x) unnamed_addr #0 {
start: …
Run Code Online (Sandbox Code Playgroud)

floating-point ieee-754

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

标签 统计

c ×3

floating-point ×2

gcc ×2

simd ×2

avx ×1

c++ ×1

clang ×1

ieee-754 ×1

intrinsics ×1

optimization ×1

sse ×1