任何人都可以解释什么是加载缓冲区以及它与失效队列的不同之处.以及存储缓冲区和写入组合缓冲区之间的区别?Paul E Mckenny的论文http://www.rdrop.com/users/paulmck/scalability/paper/whymb.2010.07.23a.pdf 很好地解释了存储缓冲区和失效队列,但不幸的是没有谈到写入组合缓冲区
代码1:
vzeroall
mov rcx, 1000000
startLabel1:
vfmadd231ps ymm0, ymm0, ymm0
vfmadd231ps ymm1, ymm1, ymm1
vfmadd231ps ymm2, ymm2, ymm2
vfmadd231ps ymm3, ymm3, ymm3
vfmadd231ps ymm4, ymm4, ymm4
vfmadd231ps ymm5, ymm5, ymm5
vfmadd231ps ymm6, ymm6, ymm6
vfmadd231ps ymm7, ymm7, ymm7
vfmadd231ps ymm8, ymm8, ymm8
vfmadd231ps ymm9, ymm9, ymm9
vpaddd ymm10, ymm10, ymm10
vpaddd ymm11, ymm11, ymm11
vpaddd ymm12, ymm12, ymm12
vpaddd ymm13, ymm13, ymm13
vpaddd ymm14, ymm14, ymm14
dec rcx
jnz startLabel1
Run Code Online (Sandbox Code Playgroud)代码2:
vzeroall
mov rcx, 1000000
startLabel2:
vmulps ymm0, ymm0, ymm0 …Run Code Online (Sandbox Code Playgroud)在x86 中查找任意操作码意味着什么(比方说)的相对快速简便的方法是什么0xC8?
搜索英特尔软件开发人员手册并不是很有趣...
是否有用于学习英特尔SSE和AVX指令的优秀C/C++教程或示例?
我在微软MSDN和英特尔网站上发现很少,但从基础知识中理解它会很棒.
我最近写了一些代码(ISO/ANSI C),并对它所取得的糟糕表现感到惊讶.长话短说,事实证明罪魁祸首就是这个floor()功能.它不仅速度慢,而且没有矢量化(使用英特尔编译器,也称为ICL).
以下是为2D矩阵中的所有单元格执行底板的一些基准:
VC: 0.10
ICL: 0.20
Run Code Online (Sandbox Code Playgroud)
将其与简单的演员比较:
VC: 0.04
ICL: 0.04
Run Code Online (Sandbox Code Playgroud)
怎么会floor()比简单演员慢得多?!它基本上是相同的(负数除外).第二个问题:有人知道超快的floor()实施吗?
PS:这是我进行基准测试的循环:
void Floor(float *matA, int *intA, const int height, const int width, const int width_aligned)
{
float *rowA=NULL;
int *intRowA=NULL;
int row, col;
for(row=0 ; row<height ; ++row){
rowA = matA + row*width_aligned;
intRowA = intA + row*width_aligned;
#pragma ivdep
for(col=0 ; col<width; ++col){
/*intRowA[col] = floor(rowA[col]);*/
intRowA[col] = (int)(rowA[col]);
}
}
}
Run Code Online (Sandbox Code Playgroud) 我今天早上在这里思考,最好的方法是将一些积极转为负面,从消极转为正面,当然,最简单的方法可能是:
int a = 10;
a = a*(-1);
Run Code Online (Sandbox Code Playgroud)
要么
int a = 10;
a = -a;
Run Code Online (Sandbox Code Playgroud)
但是,我想,我接着这样做,使用命令shift和指针......真的可以使用命令移位运算符和内存来改变值的符号吗?
现代x86 CPU将传入的指令流分解为微操作(uops 1),然后在输入准备就绪时将这些uop 无序调度.虽然基本思路很清楚,但我想了解准备好指令的具体细节,因为它会影响微优化决策.
例如,采取以下玩具循环2:
top:
lea eax, [ecx + 5]
popcnt eax, eax
add edi, eax
dec ecx
jnz top
Run Code Online (Sandbox Code Playgroud)
这基本上实现了循环(具有以下对应关系:) eax -> total, c -> ecx:
do {
total += popcnt(c + 5);
} while (--c > 0);
Run Code Online (Sandbox Code Playgroud)
通过查看uop细分,依赖链延迟等,我熟悉优化任何小循环的过程.在上面的循环中,我们只有一个携带的依赖链:dec ecx.环路(前三指令lea,imul,add)是开始新鲜每个环一个依赖关系链的一部分.
决赛dec和jne融合.因此,我们总共有4个融合域uop,以及一个仅循环携带的依赖链,延迟为1个周期.因此,基于该标准,似乎循环可以在1个周期/迭代时执行.
但是,我们也应该关注港口压力:
lea能够在端口1和5执行add可以在端口0,1,5和6执行jnz在端口6上执行因此,要进行1次循环/迭代,您几乎需要执行以下操作:
lea 必须 …我一直试图找出应用程序中的性能问题,并最终将其缩小到一个非常奇怪的问题.如果VZEROUPPER指令被注释掉,则下面的代码在Skylake CPU(i5-6500)上运行速度慢6倍.我测试了Sandy Bridge和Ivy Bridge CPU,两种版本都以相同的速度运行,有或没有VZEROUPPER.
现在我VZEROUPPER对这个代码有了一个相当好的想法,而且我认为当没有VEX编码指令并且没有调用可能包含它们的任何函数时,它对这个代码根本不重要.事实上它不支持其他支持AVX的CPU似乎支持这一点.英特尔®64和IA-32架构优化参考手册中的表11-2也是如此
那么发生了什么?
我留下的唯一理论是,CPU中存在一个错误,它错误地触发了"保存AVX寄存器的上半部分"程序,而不应该这样做.或者其他一些同样奇怪的东西.
这是main.cpp:
#include <immintrin.h>
int slow_function( double i_a, double i_b, double i_c );
int main()
{
/* DAZ and FTZ, does not change anything here. */
_mm_setcsr( _mm_getcsr() | 0x8040 );
/* This instruction fixes performance. */
__asm__ __volatile__ ( "vzeroupper" : : : );
int r = 0;
for( unsigned j = 0; j < 100000000; ++j )
{
r |= slow_function(
0.84445079384884236262,
-6.1000481519580951328, …Run Code Online (Sandbox Code Playgroud) 有没有在High Sierra(10.13)上使用Android模拟器的方法?
我跑的时候
./HAXM\ installation -u
Run Code Online (Sandbox Code Playgroud)
它说:
HAXM silent installation only supports macOS from 10.8 to 10.12 !
Run Code Online (Sandbox Code Playgroud) 我正在进行一个计算机系统课程,我试图确定,如果我的基于AMD的计算机是一个小端机器?我相信这是因为它与英特尔兼容.
具体来说,我的处理器是AMD 64 Athlon x2.
我知道这在C编程中很重要.我正在编写C程序,我正在使用的方法会受此影响.我试图弄清楚如果我在基于Intel的机器上运行程序我会得到相同的结果(假设这是小端机器).
最后,让我问一下:任何能够运行Windows(XP,Vista,2000,Server 2003等)以及Ubuntu Linux桌面的机器都是小端吗?
谢谢,
弗兰克
intel ×10
x86 ×5
performance ×4
c ×3
assembly ×2
avx ×2
sse ×2
android ×1
architecture ×1
c++ ×1
emulation ×1
endianness ×1
fma ×1
hardware ×1
opcode ×1
optimization ×1
visual-c++ ×1