Весь код был запущен на том же компьютере в Linux.Быстрый расчет логарифма
В Python:
import numpy as np
drr = abs(np.random.randn(100000,50))
%timeit np.log2(drr)
10 петель, лучший из 3: 77,9 мс на петле
В C++ (скомпилирован с G ++ -o войти ./log.cpp -std = C++ 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 мс.
Я могу понять разницу в скорости между C++ и numpy, но MATLAB превосходит все. Я столкнулся с http://fastapprox.googlecode.com/svn/trunk/fastapprox/src/fastonebigheader.h , но это делает только плавающий, а не двойной, и я не уверен, как его преобразовать в двойное.
Я также попытался это: http://hackage.haskell.org/package/approximate-0.2.2.1/src/cbits/fast.c который имеет быстрые функции журнала, и при компиляции как Numpy ufunc, работает в 20 мс, что является большим, но потеря точности является значительным.
Любые идеи о том, как достичь магической скорости log2, которую получает MATLAB?
UPDATE
Спасибо всем за комментарии, которые очень быстро и очень полезно! В самом деле, ответ - это параллелизация, т. Е. Распространение нагрузки на несколько потоков. По @morningsun предложению
% timeit numexpr.evaluate ('Журнал (УОБ)')
дает 5,6 мс, которая находится на одном уровне с MATLAB, спасибо! numexpr является MKL включен
Векторизация и параллелизме. – IKavanagh
Это типичный сценарий [SIMD] (https://en.wikipedia.org/wiki/SIMD). Сначала изучите технику векторизации кода C++. Например, попробуйте [OpenMP] (http://openmp.org/wp/). –
Компилятор C++ не может развязать вызовы log2(), поэтому он проводит много времени, отслеживая индексы цикла. И, как говорит IKavanagh, Matlab распараллеливает вычисление. Вы можете легко сделать это с помощью [OpenMP] (http://openmp.org/wp/). – YSC