向量对几乎相同的代码执行不同的求和

问题描述 投票:1回答:2

[使用g++标志-O3编译时,在数组和向量上求和的这些函数之间似乎存在性能差异:

float sum1(float* v, int length) {
    float sum = 0;
    for(int i = 0; i < length; i++) {
        sum += v[i];
    }
    return sum;
}

float sum2(std::vector<float> v) {
    return sum1(&v[0], v.size());
}

例如使用[长度为100000的[an]和sum1具有相同长度和内容的向量,sum2最终约为。在我的测试中,比sum2慢10%。测量的运行时间为:

sum1

现在,这些开销来自何处?追加您还可以找到完整的测试代码,以防万一我在这里弄错了。


完整的测试代码(用sum1: 0.279816 ms sum2: 0.307811 ms 的标志-O3编译,也用g++进行了测试):

clang++
c++ arrays performance vector stdvector
2个回答
3
投票

我认为开销来自传递矢量。

尝试通过引用代替:

#include <iostream>
#include <chrono>
#include <vector>

using namespace std;

std::vector<float> fill_vector(int length) {
    std::vector<float> ret;

    for(int i = 0; i < length; i++) {
        float r = static_cast <float> (rand()) / static_cast <float> (RAND_MAX);
        ret.push_back(r);
    }

    return ret;
}

float sum1(float* v, int length) {
    float sum = 0;
    for(int i = 0; i < length; i++) {
        sum += v[i];
    }
    return sum;
}

float sum2(std::vector<float> v) {
    return sum1(&v[0], v.size());
}

int main() {
    int iterations = 10000;
    int vector_size = 100000;

    srand(42);
    std::vector<float> v1 = fill_vector(vector_size);

    float* v2;
    v2 = &v1[0];

    std::chrono::duration<double, std::milli> duration_sum1(0);
    for(int i = 0; i < iterations; i++) {
        auto t1 = std::chrono::high_resolution_clock::now();
        float res = sum1(v2, vector_size);
        auto t2 = std::chrono::high_resolution_clock::now();
        cout << "Result sum1: " << res << endl;
        duration_sum1 += t2 - t1;
    }
    duration_sum1 /= iterations;

    std::chrono::duration<double, std::milli> duration_sum2(0);
    for(int i = 0; i < iterations; i++) {
        auto t1 = std::chrono::high_resolution_clock::now();
        float res = sum2(v1);
        auto t2 = std::chrono::high_resolution_clock::now();
        cout << "Result sum2: " << res << endl;
        duration_sum2 += t2 - t1;
    }
    duration_sum2 /= iterations;

    cout << "Durations:" << endl;
    cout << "sum1: " << duration_sum1.count() << " ms" << endl;
    cout << "sum2: " << duration_sum2.count() << " ms" << endl;
}

0
投票

您的功能float sum2(std::vector<float>& v) 取一个sum2() 按值

std::vector<float>

在这种情况下:

float sum2(std::vector<float> v) {
    return sum1(&v[0], v.size());
}

参数对象std::vector<float> vec; // ... sum2(vec); // copies vec 是从v复制初始化的。

如果您希望减少开销,则可以:

  • 移动初始化vec,而不是复制初始化它,如果您不再需要v的内容:

    vec
  • 改为参考:

    sum2(std::move(vec)); 
    
© www.soinside.com 2019 - 2024. All rights reserved.