为什么同一函数定义在一个类中的执行时间要慢10倍以上?

时间:2018-10-27 09:32:49

标签: c++ performance function optimization compiler-optimization

不确定compiler进行哪种优化,但是为什么在类中相同的函数定义要比称为全局方法的函数定义慢呢?

#include <iostream>
#include <chrono>

#define MAX_BUFFER 256
const int whileLoops = 1024 * 1024 * 10;

void TracedFunction(int blockSize) {
    std::chrono::high_resolution_clock::time_point pStart;
    std::chrono::high_resolution_clock::time_point pEnd;

    double A[MAX_BUFFER];
    double B[MAX_BUFFER];
    double C[MAX_BUFFER];

    // fill A/B
    for (int sampleIndex = 0; sampleIndex < MAX_BUFFER; sampleIndex++) {
        A[sampleIndex] = sampleIndex;
        B[sampleIndex] = sampleIndex + 1000.0;
    }

    // same traced function
    pStart = std::chrono::high_resolution_clock::now();

    int whileCounter = 0;
    while (whileCounter < whileLoops) {
        for (int sampleIndex = 0; sampleIndex < blockSize; sampleIndex++) {
            double value = A[sampleIndex] + B[sampleIndex];

            C[sampleIndex] = value;
        }

        whileCounter++;
    }

    pEnd = std::chrono::high_resolution_clock::now();
    std::cout << "execution time: " << std::chrono::duration_cast<std::chrono::milliseconds>(pEnd - pStart).count() << " ms" << " | fake result: " << A[19] << " " << B[90] << " " << C[129] << std::endl;
}

class OptimizeProcess
{
public:
    std::chrono::high_resolution_clock::time_point pStart;
    std::chrono::high_resolution_clock::time_point pEnd;

    double A[MAX_BUFFER];
    double B[MAX_BUFFER];
    double C[MAX_BUFFER];

    OptimizeProcess() {
        // fill A/B
        for (int sampleIndex = 0; sampleIndex < MAX_BUFFER; sampleIndex++) {
            A[sampleIndex] = sampleIndex;
            B[sampleIndex] = sampleIndex + 1000.0;
        }
    }

    void TracedFunction(int blockSize) {
        // same traced function
        pStart = std::chrono::high_resolution_clock::now();

        int whileCounter = 0;
        while (whileCounter < whileLoops) {
            for (int sampleIndex = 0; sampleIndex < blockSize; sampleIndex++) {
                double value = A[sampleIndex] + B[sampleIndex];

                C[sampleIndex] = value;
            }

            whileCounter++;
        }

        pEnd = std::chrono::high_resolution_clock::now();
        std::cout << "execution time: " << std::chrono::duration_cast<std::chrono::milliseconds>(pEnd - pStart).count() << " ms" << " | fake result: " << A[19] << " " << B[90] << " " << C[129] << std::endl;
    }
};

int main() {
    int blockSize = MAX_BUFFER;

    // outside class
    TracedFunction(blockSize);

    // within class
    OptimizeProcess p1;
    p1.TracedFunction(blockSize);

    std::cout << std::endl;
    system("pause");

    return 0;
}

尝试过MSVC/Oi /Ot

〜80ms和1200ms。是否使用blockSize作为compile-time的常量进行循环展开?

不确定,因为我尝试通过以下方式将blockSize设置为随机值:

std::mt19937_64 gen{ std::random_device()() };
std::uniform_real_distribution<double> dis{ 0.0, 1.0 };

int blockSize = dis(gen) * 255 + 1;

结果相同...

1 个答案:

答案 0 :(得分:2)

如果您使用GCC的最大优化标志(即O3)进行编译,那么您将获得类似的执行时间。

在一个类内执行一个函数与不执行一个类没有什么区别。执行时间。


我看到的唯一区别是创建数组的时间和方式。在第一个函数中,数组是函数的自动变量。在内部函数中,数组是类的数据成员。

在某些情况下可以起到作用。将数组设置为全局(仅创建一次),执行时间不会有所不同(无论使用O1O2还是O3)。


注意:使用O2进行编译,您将获得一个内部函数更快的执行时间(这与您提到的相反)。要精确地实现x1.35加速,请参见 Live Demo

不过,请记住,当正确完成优化时,在这种情况下使用O3,您应该不会看到任何明显的差异!