标签: icc

为什么NaN - NaN == 0.0与英特尔C++编译器?

众所周知,NaNs在算术中传播,但我找不到任何演示,所以我写了一个小测试:

#include <limits>
#include <cstdio>

int main(int argc, char* argv[]) {
    float qNaN = std::numeric_limits<float>::quiet_NaN();

    float neg = -qNaN;

    float sub1 = 6.0f - qNaN;
    float sub2 = qNaN - 6.0f;
    float sub3 = qNaN - qNaN;

    float add1 = 6.0f + qNaN;
    float add2 = qNaN + qNaN;

    float div1 = 6.0f / qNaN;
    float div2 = qNaN / 6.0f;
    float div3 = qNaN / qNaN;

    float mul1 = 6.0f * qNaN;
    float mul2 = qNaN * qNaN;

    printf( …
Run Code Online (Sandbox Code Playgroud)

c c++ floating-point icc ieee-754

299
推荐指数
3
解决办法
3万
查看次数

使用intel编译器在Windows和Linux之间的性能差异:查看程序集

我在Windows和Linux(x86-64)上运行程序.它使用相同的编译器(Intel Parallel Studio XE 2017)编译,具有相同的选项,Windows版本比Linux版本快3倍.罪魁祸首是对std :: erf的调用,在两种情况下都在英特尔数学库中解析(默认情况下,它在Windows上动态链接,在Linux上静态链接,但在Linux上使用动态链接可以提供相同的性能).

这是一个重现问题的简单程序.

#include <cmath>
#include <cstdio>

int main() {
  int n = 100000000;
  float sum = 1.0f;

  for (int k = 0; k < n; k++) {
    sum += std::erf(sum);
  }

  std::printf("%7.2f\n", sum);
}
Run Code Online (Sandbox Code Playgroud)

当我使用vTune分析这个程序时,我发现Windows和Linux版本之间的程序集有点不同.这是Windows上的调用站点(循环)

Block 3:
"vmovaps xmm0, xmm6"
call 0x1400023e0 <erff>
Block 4:
inc ebx
"vaddss xmm6, xmm6, xmm0"
"cmp ebx, 0x5f5e100"
jl 0x14000103f <Block 3>
Run Code Online (Sandbox Code Playgroud)

并在Windows上调用erf函数的开头

Block 1:
push rbp
"sub rsp, 0x40"
"lea rbp, ptr [rsp+0x20]"
"lea rcx, …
Run Code Online (Sandbox Code Playgroud)

c++ assembly x86-64 icc intel-vtune

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

为什么英特尔的编译器更喜欢NEG + ADD而非SUB?

在研究各种编译器的各种代码段的输出,我已经注意到,英特尔的C编译器(ICC)具有很强的偏爱发射一对趋势NEG+ ADD指令,其中其他的编译器将使用一个单一的SUB指令.

举个简单的例子,考虑以下C代码:

uint64_t Mod3(uint64_t value)
{
    return (value % 3);
}
Run Code Online (Sandbox Code Playgroud)

ICC将其转换为以下机器代码(无论优化级别如何):

mov       rcx, 0xaaaaaaaaaaaaaaab
mov       rax, rdi
mul       rcx
shr       rdx, 1
lea       rsi, QWORD PTR [rdx+rdx*2]
neg       rsi                            ; \  equivalent to:
add       rdi, rsi                       ; /    sub  rdi, rsi
mov       rax, rdi
ret         
Run Code Online (Sandbox Code Playgroud)

而其他编译器(包括MSVC,GCC和Clang)都将生成基本相同的代码,除了NEG+ ADD序列被单个SUB指令替换.

就像我说的,这不仅仅是ICC如何编写这个特定片段的怪癖.这是我在分析算术运算的反汇编时反复观察到的模式.我通常不会考虑这个,除了ICC是一个非常好的优化编译器,它是由拥有有关其微处理器的内幕信息的人开发的.

英特尔是否知道有关SUB其处理器上指令的实现的信息,将其分解为NEG+ ADD指令会更加优化?使用RISC样式的指令解码成更简单的μops是现代微体系结构的众所周知的优化建议,因此有可能SUB在内部分解为单个NEGADDμops,并且前端解码器使用这些实际上更有效"更简单"的指示?现代CPU很复杂,所以一切皆有可能.

然而,Agner …

x86 assembly icc micro-optimization

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

为什么矢量化循环没有性能改进

我正在调查矢量化对程序性能的影响.在这方面,我写了以下代码:

#include <stdio.h>
#include <sys/time.h>
#include <stdlib.h>

#define LEN 10000000

int main(){

    struct timeval stTime, endTime;

    double* a = (double*)malloc(LEN*sizeof(*a));
    double* b = (double*)malloc(LEN*sizeof(*b));
    double* c = (double*)malloc(LEN*sizeof(*c));

    int k;
    for(k = 0; k < LEN; k++){
        a[k] = rand();
        b[k] = rand();
    }

    gettimeofday(&stTime, NULL);

    for(k = 0; k < LEN; k++)
        c[k] = a[k] * b[k];

    gettimeofday(&endTime, NULL);

    FILE* fh = fopen("dump", "w");
    for(k = 0; k < LEN; k++)
        fprintf(fh, "c[%d] = %f\t", k, c[k]);
    fclose(fh);

    double …
Run Code Online (Sandbox Code Playgroud)

c performance simd icc

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

崩溃与icc:编译器发明写入抽象机器中不存在?

考虑以下简单程序:

#include <cstring>
#include <cstdio>
#include <cstdlib>

void replace(char *str, size_t len) {
    for (size_t i = 0; i < len; i++) {
        if (str[i] == '/') {
            str[i] = '_';
        }
    }
}

const char *global_str = "the quick brown fox jumps over the lazy dog";

int main(int argc, char **argv) {
  const char *str = argc > 1 ? argv[1] : global_str;
  replace(const_cast<char *>(str), std::strlen(str));
  puts(str);
  return EXIT_SUCCESS;
}
Run Code Online (Sandbox Code Playgroud)

它在命令行上使用(可选)字符串并打印它,并/替换为字符_.该替换功能由c_repl功能1实现.例如, …

c++ x86 simd icc language-lawyer

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

为什么malloc比英特尔的icc新7倍?

我对malloc与new进行了基准测试,以分配浮点数组.我的理解是malloc执行的操作是new执行的操作的一个子集 - malloc只分配但是新的分配和构造,尽管我不确定这对于原语是否有意义.

使用gcc对结果进行基准测试可以得出预期的行为.malloc()更快.甚至有些问题与此问题相反.

使用icc malloc可以比新的慢7倍.怎么可能?!

接下来的一切只是基准程序的细节.

对于基准测试,我使用了英特尔最近描述的协议.这是我的结果.

使用GNU的gcc分配4000个浮点数时,时钟周期已经过去了:

new memory allocation, cycles            12168
malloc allocation, cycles                 5144
Run Code Online (Sandbox Code Playgroud)

借助英特尔的icc:

new    memory allocation clock cycles     7251
malloc memory allocation clock cycles    52372
Run Code Online (Sandbox Code Playgroud)

我是如何使用malloc的:

volatile float* numbers = (float*)malloc(sizeof(float)*size);
Run Code Online (Sandbox Code Playgroud)

我是如何使用新的:

volatile float* numbers = new float[size];
Run Code Online (Sandbox Code Playgroud)

volatile是存在的,因为在之前的基准测试尝试中,我遇到了一些问题,这些编译器优化了整个函数调用并生成只存储常量的程序.(编译器选择以这种方式优化的函数实现确实比它没有的更快!)我尝试使用volatile去除只是为了确定并且结果是相同的.

我将要在两个宏之间进行基准测试的代码部分夹在中间.

功能前的宏:

#define CYCLE_COUNT_START \
asm volatile ("CPUID\n\t" \
"RDTSC\n\t" \
"mov %%edx, %0\n\t" \
"mov %%eax, %1\n\t": "=r" (cycles_high), "=r" (cycles_low):: \
"%rax", "%rbx", "%rcx", "%rdx");
Run Code Online (Sandbox Code Playgroud)

函数后面的宏:

#define CYCLE_COUNT_END \
asm volatile("RDTSCP\n\t" …
Run Code Online (Sandbox Code Playgroud)

c++ performance memory-management icc

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

GCC优化基于固定范围的for循环,就好像它具有更长,可变长度一样

我有一系列POD结构,我试图在一个字段中求和.这是一个最小的例子:

struct Item
{
    int x = 0;
    int y = 0;
};

typedef Item Items[2];

struct ItemArray
{
    Items items;

    int sum_x1() const;
    int sum_x2() const;
};

int ItemArray::sum_x1() const
{
    int total = 0;
    for (unsigned ii = 0; ii < 2; ++ii)
    {
        total += items[ii].x;
    }
    return total;
}

int ItemArray::sum_x2() const
{
    int total = 0;
    for (const Item& item : items)
    {
        total += item.x;
    }
    return total;
}
Run Code Online (Sandbox Code Playgroud)

两个sum函数做同样的事情.Clang以相同的方式编译它们.但是-O3在x86_64上的GCC 6 却没有.这是 …

c++ optimization gcc icc c++11

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

链接/运行时不同GCC版本的风险?

我正在使用英特尔的C++编译器,它在Linux上依赖于GNU提供的libc.so和libstdc ++.所以.

这是我的问题.要访问一些最新的C++ 11功能,我需要使用随GCC 4.7或更高版本提供的libstdc ++.但是我坚持使用CentOS 6.4.

在CentOS 6.4上,GCC的原生版本是4.4.但是使用名为"SCL"的RedHat和名为"devtoolset-1.1"的软件包,我可以在"/ opt"下安装GCC 4.7.

我按照上面提到的方式设置了GCC 4.7,我可以使用更新的C++ 11功能.

所以这是我的问题:如果用户只使用GCC 4.4版本的libc.so/libstdc ++来运行我的程序,那么在库路径中,由于4.4和4.7版本之间的某些不匹配,我的程序是否存在错误风险那些图书馆?

如果存在潜在问题,我可以通过静态链接GCC 4.7的libc和libstdc ++版本来解决它吗?或者,如果/当我的代码动态加载的其他库获取系统范围的GCC 4.4软件包提供的旧的libc/libstdc ++时,是否为其他问题做好准备?

c++ linux icc libstdc++ c++11

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

最简单的TBB示例

有人可以给我一个TBB示例如何:

  1. 设置活动线程的最大数量.
  2. 执行彼此独立的任务,并以类的形式呈现,而不是静态函数.

c++ tbb icc

19
推荐指数
3
解决办法
3万
查看次数

将lambda表达式传递给lambda参数c ++ 11

我想做这样的事情:

int main()
{
    auto f = [/*some variables*/](/*take lambda function*/)
    {/*something with lambda function*/};

    f([/*other variables*/](/*variables to be decided by f()*/)
    {/*something with variables*/});
}
Run Code Online (Sandbox Code Playgroud)

我知道可以将lambda传递给函数,也可以传递给lambda.以下作品:

int main()
{
    int x=0;
    int y=0;
    auto f = [x,y](double (func)(int)) -> double
    {func(0); return 0.0;};

    f([](int i) -> double
    {return 0.0;});
}
Run Code Online (Sandbox Code Playgroud)

但以下不起作用(只要我将范围变量更改为添加[x])

int main()
{
    int x=0;
    int y=0;
    auto f = [x,y](double (func)(int)) -> double
    {func(0); return 0.0;}

    f([x](int i) -> double    //[x] does not work
    {return 0.0;});
} …
Run Code Online (Sandbox Code Playgroud)

c++ lambda icc c++11

19
推荐指数
2
解决办法
3万
查看次数