我正在编写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) 我正在尝试通过研究使用-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) 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) 这个问题适用于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),但除此之外?
在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,或者有没有人有这个问题的优雅解决方案?
我正在寻找一种简单的方法来将某些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
无论如何使用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)
我知道我可以用适当的安置解决的问题 …
我想创建一个函数,它将生成任意长度的数据并返回数组.数据的内存将从数组中分配.我知道下面的简单测试代码会分配并返回指针,但我不知道的是,如果以后通过另一个调用此函数或其他函数而被覆盖是安全的.
#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++(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 ×3
c++ ×3
gcc ×2
assembly ×1
avx ×1
boilerplate ×1
c++11 ×1
constructor ×1
es6-class ×1
extend ×1
flops ×1
fma ×1
friend ×1
g++4.9 ×1
intrinsics ×1
javascript ×1
macros ×1
malloc ×1
optimization ×1
overloading ×1
performance ×1
pragma ×1
simd ×1
sse ×1
throughput ×1
x86 ×1