相关疑难解决方法(0)

为什么"使用命名空间std"被认为是不好的做法?

我已经告诉别人,编写using namespace std;代码是错误的,我应该用std::coutstd::cin直接代替.

为什么被using namespace std;认为是不好的做法?是低效还是冒着声明模糊变量(与名称std空间中的函数具有相同名称的变量)的风险?它会影响性能吗?

c++ namespaces using-directives std c++-faq

2486
推荐指数
36
解决办法
78万
查看次数

如何从C程序获得100%的CPU使用率

这是一个非常有趣的问题,所以让我设置场景.我在国家计算机博物馆工作,我们刚刚设法从1992年开始运行一台Cray Y-MP EL超级计算机,我们真的想看看它有多快!

我们认为最好的方法是编写一个简单的C程序来计算素数,并显示这需要多长时间,然后在快速的现代台式PC上运行程序并比较结果.

我们很快想出了这个代码来计算素数:

#include <stdio.h>
#include <time.h>

void main() {
    clock_t start, end;
    double runTime;
    start = clock();
    int i, num = 1, primes = 0;

    while (num <= 1000) { 
        i = 2; 
        while (i <= num) { 
            if(num % i == 0)
                break;
            i++; 
        }
        if (i == num)
            primes++;

        system("clear");
        printf("%d prime numbers calculated\n",primes);
        num++;
    }

    end = clock();
    runTime = (end - start) / (double) CLOCKS_PER_SEC;
    printf("This machine calculated all %d prime numbers under …
Run Code Online (Sandbox Code Playgroud)

c linux windows performance cray

78
推荐指数
4
解决办法
5万
查看次数

每个循环的FLOPS用于沙桥和haswell SSE2/AVX/AVX2

我对使用Sandy-Bridge和Haswell可以完成每个核心每个循环的触发器感到困惑.据我所知,对于SSE,每个核心每个周期应该为4个触发器,对于AVX/AVX2,每个核心每个周期应该有8个触发器.

这似乎在这里得到验证, 如何实现每个周期4个FLOP的理论最大值? ,这里, Sandy-Bridge CPU规范.

然而,下面的链接似乎表明,Sandy-bridge每个核心每个周期可以执行16个触发器,每个核心每个循环使用Haswell 32个触发器 http://www.extremetech.com/computing/136219-intels-haswell-is-an-前所未有-threat-to-nvidia-amd.

谁可以给我解释一下这个?

编辑:我现在明白为什么我感到困惑.我认为术语FLOP仅指单浮点(SP).我现在看到如何在每个循环中实现理论最大值4 FLOP的测试实际上是双浮点(DP),因此它们为SSE实现4个DP FLOP /周期,为AVX实现8个DP FLOP /周期.在SP上重做这些测试会很有趣.

cpu intel cpu-architecture avx flops

49
推荐指数
2
解决办法
6万
查看次数

双或浮,哪个更快?

我正在阅读"加速C++".我发现一句话说"有时double执行速度比floatC++ 快".读完句子后,我感到困惑floatdouble工作.请向我解释这一点.

c++ floating-point double

47
推荐指数
6
解决办法
4万
查看次数

为什么矢量化一般比循环更快?

为什么,在硬件执行操作的最低级别和所涉及的一般底层操作(即:运行代码时所有编程语言的实际实现的一般性),矢量化通常比循环更快?

当使用矢量化时,计算机在循环时做了什么(我说的是计算机执行的实际计算,而不是程序员编写的计算),或者它有什么不同的做法?

我一直无法说服自己为什么差异应该如此重要.我可能会说服矢量化代码在某处削减一些循环开销,但计算机仍然必须执行相同数量的操作,不是吗?例如,如果我们将大小为N的向量乘以标量,我们将使用N次乘法执行任一方式,不是吗?

language-agnostic performance vectorization low-level

46
推荐指数
3
解决办法
9057
查看次数

C++ vs Java?为什么ICC生成的代码比VC慢?

以下是C++中的一个简单循环.计时器使用QueryPerformanceCounter()并且非常准确.我发现Java需要60%的时间用C++,这不可能是什么?!我在这做错了什么?即使是严格的别名(这里没有包含在代码中)也没有任何帮助......

long long var = 0;
std::array<int, 1024> arr;
int* arrPtr = arr.data();
CHighPrecisionTimer timer;

for(int i = 0; i < 1024; i++) arrPtr[i] = i;

timer.Start();

for(int i = 0; i < 1024 * 1024 * 10; i++){
    for(int x = 0; x < 1024; x++){
        var += arrPtr[x];
    }
}

timer.Stop();

printf("Unrestricted: %lld us, Value = %lld\n", (Int64)timer.GetElapsed().GetMicros(), var);
Run Code Online (Sandbox Code Playgroud)

这个C++在大约9.5秒内完成.我正在使用英特尔编译器12.1与主机处理器优化(特别是我的)和一切最大化.所以这是英特尔编译器的最佳选择!自动并行化有趣地消耗70%的CPU而不是25%但是不能更快地完成工作;)...

现在我使用以下Java代码进行比较:

    long var = 0;
    int[] arr = new int[1024];

    for(int i = 0; i < 1024; i++) …
Run Code Online (Sandbox Code Playgroud)

c++ java performance

45
推荐指数
4
解决办法
4828
查看次数

C代码循环性能

我的应用程序中有一个乘法添加内核,我想提高它的性能.

我使用英特尔酷睿i7-960(3.2 GHz时钟)并已使用SSE内在函数手动实现内核,如下所示:

 for(int i=0; i<iterations; i+=4) {
    y1 = _mm_set_ss(output[i]);
    y2 = _mm_set_ss(output[i+1]);
    y3 = _mm_set_ss(output[i+2]);
    y4 = _mm_set_ss(output[i+3]);

    for(k=0; k<ksize; k++){
        for(l=0; l<ksize; l++){
            w  = _mm_set_ss(weight[i+k+l]);

            x1 = _mm_set_ss(input[i+k+l]);
            y1 = _mm_add_ss(y1,_mm_mul_ss(w,x1));
            …
            x4 = _mm_set_ss(input[i+k+l+3]);
            y4 = _mm_add_ss(y4,_mm_mul_ss(w,x4));
        }
    }
    _mm_store_ss(&output[i],y1);
    _mm_store_ss(&output[i+1],y2);
    _mm_store_ss(&output[i+2],y3);
    _mm_store_ss(&output[i+3],y4);
 }
Run Code Online (Sandbox Code Playgroud)

我知道我可以使用压缩的fp向量来提高性能,我已经成功完成了,但我想知道为什么单个标量代码无法满足处理器的峰值性能.

我的机器上的这个内核的性能是每个周期大约1.6个FP操作,而每个周期最大的是2个FP操作(因为FP add + FP mul可以并行执行).

如果我对研究生成的汇编代码是正确的,理想的时间表将如下所示,其中mov指令需要3个周期,从依赖指令的加载域到FP域的切换延迟需要2个周期,FP乘以4个循环,FP添加需要3个循环.(注意,乘法 - > add的依赖性不会导致任何切换延迟,因为操作属于同一个域).

时间表

根据测量的性能(最大理论性能的约80%),每8个周期有大约3个指令的开销.

我想要:

  • 摆脱这种开销,或
  • 解释它来自哪里

当然,存在缓存未命中和数据错位的问题,这可能会增加移动指令的延迟,但是还有其他因素可以在这里发挥作用吗?像寄存器读取档位或什么?

我希望我的问题很明确,在此先感谢您的回复!


更新:内循环的程序集如下所示:

...
Block 21: 
  movssl  (%rsi,%rdi,4), %xmm4 
  movssl  (%rcx,%rdi,4), %xmm0 
  movssl  0x4(%rcx,%rdi,4), %xmm1 …
Run Code Online (Sandbox Code Playgroud)

c performance assembly intel instructions

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

为什么JavaScript看起来比C++快4倍?

很长一段时间以来,我一直认为C++比JavaScript更快.然而,今天我制作了一个基准脚本来比较两种语言中浮点计算的速度,结果令人惊叹!

JavaScript似乎比C++快4倍!

我让这两种语言在我的i5-430M笔记本电脑上做同样的工作,执行a = a + b了1亿次.C++大约需要410毫秒,而JavaScript大约需要120毫秒.

我真的不知道为什么JavaScript在这种情况下运行如此之快.有谁能解释一下?

我用于JavaScript的代码是(使用Node.js运行):

(function() {
    var a = 3.1415926, b = 2.718;
    var i, j, d1, d2;
    for(j=0; j<10; j++) {
        d1 = new Date();
        for(i=0; i<100000000; i++) {
            a = a + b;
        }
        d2 = new Date();
        console.log("Time Cost:" + (d2.getTime() - d1.getTime()) + "ms");
    }
    console.log("a = " + a);
})();
Run Code Online (Sandbox Code Playgroud)

C++的代码(由g ++编译)是:

#include <stdio.h>
#include <ctime>

int main() {
    double a = 3.1415926, b = 2.718;
    int i, …
Run Code Online (Sandbox Code Playgroud)

javascript c++ floating-point performance benchmarking

29
推荐指数
4
解决办法
5万
查看次数

x86的MOV真的可以"免费"吗?为什么我不能重现这个呢?

我一直看到人们声称MOV指令可以在x86中免费,因为寄存器重命名.

对于我的生活,我无法在一个测试用例中验证这一点.每个测试用例我尝试揭穿它.

例如,这是我用Visual C++编译的代码:

#include <limits.h>
#include <stdio.h>
#include <time.h>

int main(void)
{
    unsigned int k, l, j;
    clock_t tstart = clock();
    for (k = 0, j = 0, l = 0; j < UINT_MAX; ++j)
    {
        ++k;
        k = j;     // <-- comment out this line to remove the MOV instruction
        l += j;
    }
    fprintf(stderr, "%d ms\n", (int)((clock() - tstart) * 1000 / CLOCKS_PER_SEC));
    fflush(stderr);
    return (int)(k + j + l);
}
Run Code Online (Sandbox Code Playgroud)

这为循环生成以下汇编代码(随意生成这个你想要的;你显然不需要Visual C++):

LOOP:
    add edi,esi
    mov …
Run Code Online (Sandbox Code Playgroud)

c x86 assembly cpu-registers micro-optimization

23
推荐指数
2
解决办法
2113
查看次数

GCC中的FMA3:如何启用

我有一个i5-4250U,它有AVX2和FMA3.我正在测试Linux上的GCC 4.8.1中的一些密集矩阵乘法代码.下面是我编译的三种不同方式的列表.

SSE2:     gcc matrix.cpp -o matrix_gcc -O3 -msse2 -fopenmp
AVX:      gcc matrix.cpp -o matrix_gcc -O3 -mavx  -fopenmp
AVX2+FMA: gcc matrix.cpp -o matrix_gcc -O3 -march=native -fopenmp -ffast-math
Run Code Online (Sandbox Code Playgroud)

SSE2和AVX版本的性能明显不同.但是,AVX2 + FMA并不比AVX版本好.我不明白这一点.假设没有FMA,我获得了超过80%的CPU峰值触发器,但我认为我应该能够用FMA做得更好.矩阵乘法应直接受益于FMA.我基本上是在AVX中同时做八个点产品.当我检查march=native它给出:

cc -march=native -E -v - </dev/null 2>&1 | grep cc1 | grep fma 
...-march=core-avx2 -mavx -mavx2 -mfma -mno-fma4 -msse4.2 -msse4.1 ...
Run Code Online (Sandbox Code Playgroud)

所以我可以看到它已启用(只是为了确保我添加-mfma但它没有区别). ffast-math应该允许宽松的浮点模型如何在SSE/AVX中使用融合乘法 - 加法(FMA)指令

编辑:

基于Mysticial的评论我继续使用_mm256_fmadd_ps,现在AVX2 + FMA版本更快. 我不确定为什么编译器不会为我这样做. 对于超过1000x1000的矩阵,我现在得到大约80 GFLOPS(没有FMA的110%的峰值触发器).如果有人不信任我的峰值翻牌计算,这就是我所做的.

peak flops (no FMA) = frequency * simd_width * ILP * cores …
Run Code Online (Sandbox Code Playgroud)

c++ gcc intel avx fma

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