我使用英特尔®架构代码分析器(IACA)发现了一些意想不到的东西(对我而言).
以下指令使用[base+index]寻址
addps xmm1, xmmword ptr [rsi+rax*1]
Run Code Online (Sandbox Code Playgroud)
根据IACA没有微熔丝.但是,如果我用[base+offset]这样的
addps xmm1, xmmword ptr [rsi]
Run Code Online (Sandbox Code Playgroud)
IACA报告它确实融合了.
英特尔优化参考手册的第2-11节给出了以下"可以由所有解码器处理的微融合微操作"的示例
FADD DOUBLE PTR [RDI + RSI*8]
Run Code Online (Sandbox Code Playgroud)
和Agner Fog的优化装配手册也给出了使用[base+index]寻址的微操作融合的例子.例如,请参见第12.2节"Core2上的相同示例".那么正确的答案是什么?
代码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)我将一些程序集与一些c链接起来测试函数调用的成本,使用以下程序集和c源代码(分别使用fasm和gcc)
部件:
format ELF
public no_call as "_no_call"
public normal_call as "_normal_call"
section '.text' executable
iter equ 100000000
no_call:
mov ecx, iter
@@:
push ecx
pop ecx
dec ecx
cmp ecx, 0
jne @b
ret
normal_function:
ret
normal_call:
mov ecx, iter
@@:
push ecx
call normal_function
pop ecx
dec ecx
cmp ecx, 0
jne @b
ret
Run Code Online (Sandbox Code Playgroud)
c来源:
#include <stdio.h>
#include <time.h>
extern int no_call();
extern int normal_call();
int main()
{
clock_t ct1, ct2;
ct1 = clock();
no_call();
ct2 = clock(); …Run Code Online (Sandbox Code Playgroud) 这两个代码片段做同样的事情:将两个float数组一起添加并将结果存储回它们.
内联汇编程序:
void vecAdd_SSE(float* v1, float* v2) {
_asm {
mov esi, v1
mov edi, v2
movups xmm0, [esi]
movups xmm1, [edi]
addps xmm0, xmm1
movups [esi], xmm0
movups [edi], xmm0
}
}
Run Code Online (Sandbox Code Playgroud)
普通C++代码:
void vecAdd_Std(float* v1, float* v2) {
v1[0] = v1[0]+ v2[0];
v1[1] = v1[1]+ v2[1];
v1[2] = v1[2]+ v2[2];
v1[3] = v1[3]+ v2[3];
v2[0] = v1[0];
v2[1] = v1[1];
v2[2] = v1[2];
v2[3] = v1[3];
}
Run Code Online (Sandbox Code Playgroud)
C++代码的反汇编(在调试模式下进行反汇编,因为由于某种原因我无法在发布模式下查看反汇编):
void vecAdd_Std(float* v1, float* v2) {
push ebp
mov ebp,esp …Run Code Online (Sandbox Code Playgroud) 我有一个class A具有std::vector<int>作为属性.
A在A创建实例时需要填充此向量.计算可能需要一些时间,我想知道是否:
我不熟悉元编程,我现在找不到办法.这不是特定于操作系统的问题.
这是A.cpp文件:
#include "A.h"
#define SIZEV 100
A::A()
{
fillVector();
}
void A::fillVector()
{
// m_vector is an attribute of class "A"
// EXPECTATION 1 : fill the vector with the following calculation at compile time
const int a=5;
const int b=7;
const int c=9;
for(int i=0;i<SIZEV;i++){
for(int j=0;j<SIZEV;j++){
for(int k=0;k<SIZEV;k++){
this->m_vector.push_back(a*i+b*j+c*k);
}
}
}
// EXPECTATION 2 : sort the vector as compile time
} …Run Code Online (Sandbox Code Playgroud) 我发现了一个有趣的现象:
#include<stdio.h>
#include<time.h>
int main() {
int p, q;
clock_t s,e;
s=clock();
for(int i = 1; i < 1000; i++){
for(int j = 1; j < 1000; j++){
for(int k = 1; k < 1000; k++){
p = i + j * k;
q = p; //Removing this line can increase running time.
}
}
}
e = clock();
double t = (double)(e - s) / CLOCKS_PER_SEC;
printf("%lf\n", t);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我在i5-5257U Mac OS上使用GCC 7.3.0来编译代码 …