[使用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++
我认为开销来自传递矢量。
尝试通过引用代替:
#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;
}
您的功能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));