Весь код был запущен на том же компьютере в Linux.
В python:
import numpy as np
drr = abs(np.random.randn(100000,50))
%timeit np.log2(drr)
10 петель, лучше всего 3: 77,9 мс за цикл
В С++ (скомпилировано с g++ -o log./log.cpp -std = С++ 11 -O3):
#include <iostream>
#include <iomanip>
#include <string>
#include <map>
#include <random>
#include <ctime>
int main()
{
std::mt19937 e2(0);
std::normal_distribution<> dist(0, 1);
const int n_seq = 100000;
const int l_seq = 50;
static double x[n_seq][l_seq];
for (int n = 0;n < n_seq; ++n) {
for (int k = 0; k < l_seq; ++k) {
x[n][k] = abs(dist(e2));
if(x[n][k] <= 0)
x[n][k] = 0.1;
}
}
clock_t begin = clock();
for (int n = 0; n < n_seq; ++n) {
for (int k = 0; k < l_seq; ++k) {
x[n][k] = std::log2(x[n][k]);
}
}
clock_t end = clock();
Работает через 60 мс
В MATLAB:
abr = abs(randn(100000,50));
tic;abr=log2(abr);toc
Истекшее время составляет 7,8 мс.
Я могу понять разницу в скорости между С++ и numpy, но MATLAB превосходит все. Я столкнулся http://fastapprox.googlecode.com/svn/trunk/fastapprox/src/fastonebigheader.h но это только float, а не double, и я не уверен, как преобразовать его в double.
Я также пробовал: http://hackage.haskell.org/package/approximate-0.2.2.1/src/cbits/fast.c который имеет быстрые функции журнала, а когда скомпилирован как numpy ufunc, работает в 20 мс, что отлично, но потеря точности является значительной.
Любые идеи о том, как достичь магической скорости log2, которую получает MATLAB?
UPDATE
Спасибо всем за комментарии, это было очень быстро и очень полезно! В самом деле, ответ - это параллелизация, т.е. Распространение нагрузки на несколько потоков. Следуя предложению @morningsun,
% timeit numexpr.evaluate('log (drr)')
дает 5.6 мс, что наравне с MATLAB, спасибо! numexpr включен MKL