为什么 C++ 代码实现的性能不比 python 实现更好?
Why c++ code implementation is not performing better than the python implementation?
我正在为数据点寻找最近的邻居进行基准测试。我的 c++ 实现和 python 实现花费的执行时间几乎相同。不应该是 c++ 比原始 python 实现更好。
- C++ 执行时间:8.506秒
- Python 执行时间:8.7202 秒
C++代码:
#include <iostream>
#include <random>
#include <map>
#include <cmath>
#include <numeric>
#include <algorithm>
#include <chrono>
#include <vector> // std::iota
using namespace std;
using namespace std::chrono;
double edist(double* arr1, double* arr2, uint n) {
double sum = 0.0;
for (int i=0; i<n; i++) {
sum += pow(arr1[i] - arr2[i], 2);
}
return sqrt(sum); }
template <typename T> vector<size_t> argsort(const vector<T> &v) {
// initialize original index locations
vector<size_t> idx(v.size()); iota(idx.begin(), idx.end(), 0);
// sort indexes based on comparing values in v
sort(idx.begin(), idx.end(),
[&v](size_t i1, size_t i2) {return v[i1] < v[i2];});
return std::vector<size_t>(idx.begin() + 1, idx.end()); }
int main() {
uint N, M;
// cin >> N >> M;
N = 1000;
M = 800;
double **arr = new double*[N];
std::random_device rd; // obtain a random number from hardware
std::mt19937 eng(rd()); // seed the generator
std::uniform_real_distribution<> distr(10.0, 60.0);
for (int i = 0; i < N; i++) {
arr[i] = new double[M];
for(int j=0; j < M; j++) {
arr[i][j] = distr(eng);
}
}
auto start = high_resolution_clock::now();
map<int, vector<size_t> > dist;
for (int i=0; i<N; i++) {
vector<double> distances;
for(int j=0; j<N; j++) {
distances.push_back(edist(arr[i], arr[j], N));
}
dist[i] = argsort(distances);
}
auto stop = high_resolution_clock::now();
auto duration = duration_cast<microseconds>(stop-start);
int dur = duration.count();
cout<<"Time taken by code: "<<dur<<" microseconds"<<endl;
cout<<" In seconds: "<<dur/pow(10,6);
return 0; }
蟒蛇代码:
import time
import numpy as np
def comp_inner_raw(i, x):
res = np.zeros(x.shape[0], dtype=np.float64)
for j in range(x.shape[0]):
res[j] = np.sqrt(np.sum((i-x[j])**2))
return res
def nearest_ngbr_raw(x): # x = [[1,2,3],[4,5,6],[7,8,9]]
#print("My array: ",x)
dist = {}
for idx,i in enumerate(x):
#lst = []
lst = comp_inner_raw(i,x)
s = np.argsort(lst)#[1:]
sorted_array = np.array(x)[s][1:]
dist[idx] = s[1:]
return dist
arr = np.random.rand(1000, 800)
start = time.time()
table = nearest_ngbr_raw(arr)
print("Time taken to execute the code using raw python is {}".format(time.time()-start))
编译命令:
g++ -std=c++11 knn.cpp -o knn
C++ Ubuntu 的编译器 (G++) 版本 18.04.1:7.4.0
用c++11编码
数字版本: 1.16.2
编辑尝试使用编译器优化,现在大约需要 1 秒。 是否可以从编码或任何其他角度进一步优化此 C++ 代码?
这个 c++ 代码可以从编码或任何其他角度进一步优化吗?
我可以看到至少三个优化。前两个很容易,绝对应该完成,但在我的测试中,它们最终不会对运行时产生可衡量的影响。第三个需要最低限度地重新思考代码。
-
edist
计算成本高昂的平方根,但您仅使用距离进行成对比较。由于平方根函数是单调递增的,因此对比较结果没有影响。同样,pow(x, 2)
可以替换为x * x
,这有时更快:double edist(std::vector<double> const& arr1, std::vector<double> const& arr2, uint n) { double sum = 0.0; for (unsigned int i = 0; i < n; i++) { auto const diff = arr1[i] - arr2[i]; sum += diff * diff; } return sum; }
-
argsort
执行复制,因为它返回不包括第一个元素的索引。如果改为包含第一个元素(将 return 语句更改为return idx;
),则可以避免可能代价高昂的副本。 -
您的矩阵表示为嵌套数组(并且由于某种原因,您使用原始指针而不是嵌套
std::vector
)。通常,将矩阵表示为连续的 N*M 数组更有效:std::vector<double> arr(N * M);
.这也是 numpy 在内部表示矩阵的方式。这需要更改代码来计算索引。
相关文章:
- 如何在c++中使用引用实现类似python的行为
- 我如何在C++像在 Python 中一样实现 f 字符串?
- 如何使用列表/数组在C++中实现 Python "... not in ..."?
- 在C++中实现类似 python "map"函数的问题:调用类成员函数
- 在 c++ 或 python 中生成一个体面的视差图以在 Raspberry Pi 上实现的最佳方法(算法或函数)是什么
- 如何创建一个接口,允许我访问C++中的按钮(和其他ui)函数,该函数是使用python中的MFC实现的
- 了解C++中的pop_heap,以便在 Python 中实现
- 如何为C++库实现 Python 接口
- C++ 和 Python 实现之间的不同伪随机数
- 为什么 C++ 代码实现的性能不比 python 实现更好?
- 有没有办法在C++中实现 Python 的 join()?
- 如何在python中实现CRTP功能
- 在C 中实现Python np.fromstring()
- 使用L1CPUCache实现c++算法的Python
- 在C++中实现类似 Python 的列表
- 我怎样才能用另一种语言(也许C++)实现Python集
- 快速排序实现- Python
- 如何在c++中实现Python函数exec()
- 在C++中实现 Python 的'if X in List'
- 有没有办法在C++中实现Python的"separator".join()的模拟?