小编cod*_*imp的帖子

为什么其中一个比另一个快得多?

我正在编写C++代码来查找内存中非0xFF的第一个字节.为了利用bitscanforward,我编写了一个我非常喜欢的内联汇编代码.但是对于"可读性"以及未来的校对(即SIMD矢量化),我想我会给g ++优化器一个机会.g ++没有矢量化,但它确实得到了我所做的几乎相同的非SIMD解决方案.但由于某种原因,它的版本运行速度慢得多,速度慢260000倍(即我必须循环我的版本260,000x才能达到相同的执行时间).我除了一些差异,但不是那么多!有人可以指出它为什么会这样吗?我只是想知道在未来的内联汇编代码中出错.

C++的起点如下,(就计数准确性而言,此代码中存在一个错误,但我已将其简化为此速度测试):

uint64_t count3 (const void *data, uint64_t const &nBytes) {
      uint64_t count = 0;
      uint64_t block;
      do {
         block = *(uint64_t*)(data+count);
         if ( block != (uint64_t)-1 ) {
/*       count += __builtin_ctz(~block);   ignore this for speed test*/
            goto done;
          };
        count += sizeof(block);
      } while ( count < nBytes );
done:
      return (count>nBytes ? nBytes : count);
}
Run Code Online (Sandbox Code Playgroud)

汇编代码g ++提出的是:

_Z6count3PKvRKm:
.LFB33:
    .cfi_startproc
    mov rdx, QWORD PTR [rsi]
    xor eax, eax
    jmp .L19
    .p2align 4,,10
    .p2align 3 …
Run Code Online (Sandbox Code Playgroud)

c++ performance x86 inline-assembly

10
推荐指数
2
解决办法
752
查看次数

优化C代码中的汇编代码冗余

我正在尝试通过研究使用-O3优化在gcc中编译的简单C代码来学习矢量化.更具体地说,编译器的矢量化程度如何.这是一个个人的旅程,能够通过更复杂的计算来验证gcc -O3的性能.我理解传统的观点是编译器比人更好,但我从不认为这种智慧是理所当然的.

然而,在我的第一个简单测试中,我发现一些选择gcc非常奇怪,而且老实说,在优化方面非常疏忽.我愿意假设有一些编译器是有目的的,并且知道一些关于CPU的信息(在这种情况下是Intel i5-2557M),我不知道.但我需要知识渊博的人做一些确认.

我的简单测试代码(段)是:

int i;
float a[100];

for (i=0;i<100;i++) a[i]= (float) i*i;
Run Code Online (Sandbox Code Playgroud)

与for循环对应的结果汇编代码(段)如下:

.L6:                        ; loop starts here
    movdqa  xmm0, xmm1      ; copy packed integers in xmm1 to xmm0
.L3:
    movdqa  xmm1, xmm0      ; wait, what!?  WHY!?  this is redundant.
    cvtdq2ps    xmm0, xmm0  ; convert integers to float
    add rax, 16             ; increment memory pointer for next iteration
    mulps   xmm0, xmm0      ; pack square all integers in xmm0
    paddd   xmm1, xmm2      ; …
Run Code Online (Sandbox Code Playgroud)

c optimization assembly gcc

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

immintrin.h 的替代品

immintrin.h在 c/c++ 中,我认为,由 提供的显式向量化内在函数是一个拼凑。也就是说,对于每个CPU指令集(例如SSE、AVX2、AVX512等)和每个数字类型(即float、double、int等),对于相同的基本操作都有一个独特的函数,例如_mm_add_epi8_mm_add_epi16、、、_mm256_add_epi8都是_mm256_add_epi16为了基础+。因此,如果您使用 AVX 的内在函数进行编码,则在升级到 AVX2 以及升级到 AVX512 等时必须重新编码。

另一方面,一些编译器的基本内置运算符(即“+”、“-”等)似乎在所有类型(向量和非向量)和一些混合类型操作上都能很好地工作(提供数据对齐) (如下面的代码片段所示),从而带来更好的可读性和可扩展性(使用 simd 指令集)。

// no need for #include "immintrin.h"

#ifndef __AVX2__
#define SIMD_LEN 16
#else
#define SIMD_LEN 32
#endif

typedef int num_t;

num_t a[N], b[N];

// for any num_t and SIMD_LEN, explicitly vectorize b[n] = 2*a[n] + 4 

typedef num_t    vec_t __attribute__ ((__vector_size__ (SIMD_LEN)));

vec_t *vA = (vec_t*)a;
vec_t *vB = (vec_t*)b;

int nNums = SIMD_LEN/sizeof(num_t);

for (int …
Run Code Online (Sandbox Code Playgroud)

c gcc simd vectorization intrinsics

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

对于Intel Haswell上的XMM/YMM FP操作,可以使用FMA代替ADD吗?

这个问题适用于Haswell上带有XMM/YMM寄存器的压缩单预备浮点运算.

因此,根据Agner Fog 提供的令人敬畏的,令人敬畏的 ,我知道MUL可以在端口p0和p1上完成(recp thruput为0.5),而只有ADD只在端口p1上完成(recp thruput为1) ).我可以除了这个限制,但我也知道FMA可以在端口p0或p1上完成(recp吞吐量为0.5).因此,当我的FMA可以使用p0或p1并同时执行ADD和MUL时,为什么普通ADD仅限于p1是令人困惑的.我误解了桌子吗?或者有人可以解释为什么会这样?

也就是说,如果我的读数是正确的,为什么英特尔不会仅使用FMA op作为普通MUL和普通ADD的基础,从而增加ADD和MUL的吞吐量.或者,什么会阻止我使用两个同时独立的FMA操作来模拟两个同时独立的ADD操作?做ADD-by-FMA有哪些处罚?显然,使用的寄存器数量更多(ADD为2 reg,而FMA为ADD为3 reg),但除此之外?

sse avx flops throughput fma

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

Javascript,扩展ES6类setter将继承getter

在Javascript中,使用以下插图代码:

class Base {
   constructor() {  this._val = 1   }
   get val()     { return this._val }
}

class Xtnd extends Base {
   set val(v)    { this._val = v }
}

let x = new Xtnd();
x.val = 5;
console.log(x.val);  // prints 'undefined'
Run Code Online (Sandbox Code Playgroud)

实例x不会get val()...Base类继承.实际上,Javascript在存在setter时将缺少getter视为未定义.

我有一种情况,其中我有许多类都具有完全相同的getter集但是唯一的setter.目前,我只是复制每个类中的getter,但我正在重构并想要消除冗余代码.

有没有办法告诉JS保持基类的getter,或者有没有人有这个问题的优雅解决方案?

javascript boilerplate extend es6-class

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

在代码中本地化g ++编译选项

我正在寻找一种简单的方法来将某些g ++(g ++ - 4.9特定的)编译选项本地化到某些代码行或至少是目标函数.我感兴趣一般来说,还特意到-fast-math,-ffinite-math-only-fno-signed-zeros选项.

我认为可以使用make实用程序在*.cpp文件级别进行本地化,但我希望有一种方法可以在代码本身中通过#pragma或__attribute__等来启用它.我想这样做不仅可以最大限度地减少对外部文件的依赖性(即不正确的风险makefile),而且还希望将某些FP行为超本地化为函数内的特定方程.

或者,如果不能通过内联指令本地化FP行为,如果在项目构建中未启用所需的编译器指令(例如makefile丢失或不适当地修改),我该怎么做才能至少触发编译时错误.

我认为这种内联优化可能是编译器特定的,在这种情况下是g ++,但这是我愿意采取的妥协.

pragma compiler-directives compiler-optimization c++11 g++4.9

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

c ++重载构造函数与新类型/类和朋友

无论如何使用friend使用新定义的结构重载已经声明的struct的构造函数.例如,在下面的简单示例中,我想struct A使用一个使用struct B,但不修改Ah来重载构造函数.

main.cpp中

#include "A.h"
#include "B.h"

int main() {
    B x(2);
    A y(B); 
};
Run Code Online (Sandbox Code Playgroud)

struct A {
    float a;
    A(float);
};

A::A(float f)   { a=f; };
Run Code Online (Sandbox Code Playgroud)

BH

struct B {
    float b;
    B(float);
    B(A);
};

B::B(float f)   { b=f;   };
B::B(A s)       { b=s.a; };

A::A(B s){ a=s.b; };
// ^^^----obviously error since A(B) is not declared, 
// but how can I make this work without changing A.h?
Run Code Online (Sandbox Code Playgroud)

我知道我可以用适当的安置解决的问题 …

c++ constructor overloading friend

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

使用交流功能分配内存是否安全

我想创建一个函数,它将生成任意长度的数据并返回数组.数据的内存将从数组中分配.我知道下面的简单测试代码会分配并返回指针,但我不知道的是,如果以后通过另一个调用此函数或其他函数而被覆盖是安全的.

#include <stdio.h>

float* CreateFloatArray(unsigned int N) {
    float *array = (float*) malloc(N*sizeof(float));
    return array;
}

int main() {
   float *a = CreateFloatArray(10);
//   free(a);
   float *b = CreateFloatArray(10);

   printf ("%d %d\n",a,b);
   return 0;
}
Run Code Online (Sandbox Code Playgroud)

需要明确的是,这段代码不是我的实际应用程序,而是一个简单的测试.

最后,测试代码打印两个已分配内存块的地址.如果我free(a)在两次调用之间插入命令,则a和b的地址相同; 否则,他们相距甚远.

很明显,这个简单的测试工作在分配不同的内存块,没有重叠,但我正在寻找保证,从更有知识的人,在整个程序执行过程中永远不会有内存重叠,无论我有多少次叫这个功能?(当然,了解到函数内部的粗心malloc是泄漏内存的好方法).

c malloc memory-management

0
推荐指数
1
解决办法
71
查看次数

C++连接宏定义

在C++(G ++具体)中,可以连接两个没有空格的宏定义来创建第三个定义吗?例如,我该怎么做

#define _LOAD _mm256_load
#define _FLOAT ps
Run Code Online (Sandbox Code Playgroud)

并因此对它们进行操作

#define _LOAD_FLOAT   ****do something with _FLOAT and _LOAD here *****
Run Code Online (Sandbox Code Playgroud)

创建功能上等同于以下内容的定义:

#define _LOAD_FLOAT _mm256_load_ps
Run Code Online (Sandbox Code Playgroud)

c++ macros concatenation c-preprocessor

0
推荐指数
1
解决办法
95
查看次数