这是我进行的比较。 np.argsort
在float1 ndarray上计时,该数组由1,000,000个元素组成。
In [1]: import numpy as np
In [2]: a = np.random.randn(1000000)
In [3]: a = a.astype(np.float32)
In [4]: %timeit np.argsort(a)
86.1 ms ± 1.59 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
这是一个C ++程序,执行相同的过程,但对指向this answer的向量进行了操作。
#include <iostream>
#include <vector>
#include <cstddef>
#include <algorithm>
#include <opencv2/opencv.hpp>
#include <numeric>
#include <utility>
int main()
{
std::vector<float> numbers;
for (int i = 0; i != 1000000; ++i) {
numbers.push_back((float)rand() / (RAND_MAX));
}
double e1 = (double)cv::getTickCount();
std::vector<size_t> idx(numbers.size());
std::iota(idx.begin(), idx.end(), 0);
std::sort(idx.begin(), idx.end(), [&numbers](const size_t &a, const size_t &b)
{ return numbers[a] < numbers[b];});
double e2 = (double)cv::getTickCount();
std::cout << "Finished in " << 1000 * (e2 - e1) / cv::getTickFrequency() << " milliseconds." << std::endl;
return 0;
}
它打印Finished in 525.908 milliseconds.
,并且比numpy版本慢得多。有人能解释一下np.argsort
这么快的原因吗?谢谢。
Edit1:np.__version__
返回1.15.0
,它在Python 3.6.6 |Anaconda custom (64-bit)
上运行,并且g++ --version
打印8.2.0。操作系统是Manjaro Linux。
Edit2:我很想在已删除,因为我在拔掉笔记本电脑的DC适配器的情况下错误地运行了测试,这会导致测试变慢。在公平竞争中,C阵列和矢量版本的性能相同(大约需要100毫秒)。-O2
中使用-O3
和g++
标志进行编译,结果在216.515毫秒和205.017毫秒之内。这是一个改进,但仍比numpy版本慢。 (Referring to this question)
Edit3:另一种方法是将向量替换为C,例如数组:float numbers[1000000];
。之后,运行时间约为100ms(+/- 5ms)。完整代码在这里:
#include <iostream>
#include <vector>
#include <cstddef>
#include <algorithm>
#include <opencv2/opencv.hpp>
#include <numeric>
#include <utility>
int main()
{
//std::vector<float> numbers;
float numbers[1000000];
for (int i = 0; i != 1000000; ++i) {
numbers[i] = ((float)rand() / (RAND_MAX));
}
double e1 = (double)cv::getTickCount();
std::vector<size_t> idx(1000000);
std::iota(idx.begin(), idx.end(), 0);
std::sort(idx.begin(), idx.end(), [&numbers](const size_t &a, const size_t &b)
{ return numbers[a] < numbers[b];});
double e2 = (double)cv::getTickCount();
std::cout << "Finished in " << 1000 * (e2 - e1) / cv::getTickFrequency() << " milliseconds." << std::endl;
return 0;
}
答案 0 :(得分:2)
我接受了您的实施,并用10000000
个项目对其进行了评估。花了大约1.7秒。
现在我介绍了一个课程
class valuePair {
public:
valuePair(int idx, float value) : idx(idx), value(value){};
int idx;
float value;
};
with初始化为
std::vector<valuePair> pairs;
for (int i = 0; i != 10000000; ++i) {
pairs.push_back(valuePair(i, (double)rand() / (RAND_MAX)));
}
和排序
std::sort(pairs.begin(), pairs.end(), [&](const valuePair &a, const valuePair &b) { return a.value < b.value; });
此代码将运行时间缩短至1.1秒。我认为这是由于具有更好的缓存一致性,但与python结果仍然相去甚远。
答案 1 :(得分:1)
想法:
不同的基础算法: np.argsort
默认使用quicksort,C++
中的实现可能取决于您的编译器。
函数调用开销:我不确定根据this post C++
编译器是否内联您的比较函数。如果没有,调用此函数也可能会带来一些开销。
编译器标志?