Tutto il codice è stato eseguito sulla stessa macchina su linux.Calcolo logaritmo veloce
In pitone:
import numpy as np
drr = abs(np.random.randn(100000,50))
%timeit np.log2(drr)
10 cicli, più di 3: 77,9 ms per loop
In C++ (compilato con g ++ -o log ./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();
Viene eseguito in 60 ms
in MATLAB:
abr = abs(randn(100000,50));
tic;abr=log2(abr);toc
Il tempo trascorso è 7,8 ms.
Riesco a capire la differenza di velocità tra C++ e numpy, ma MATLAB batte tutto. Mi sono imbattuto in ma questo è solo mobile, non doppio, e non sono sicuro di come convertirlo in doppio.
Ho anche provato questo: http://hackage.haskell.org/package/approximate-0.2.2.1/src/cbits/fast.c che ha funzioni di registro veloci, e quando compilato come ufunc NumPy, viene eseguito in 20 ms, che è grande, ma la perdita di precisione è significativo.
Qualche idea su come ottenere la magica velocità log2 che MATLAB ottiene?
UPDATE
Grazie a tutti per i commenti, che era molto veloce e molto utile! In effetti, la risposta è la parallelizzazione, cioè la diffusione del carico su più thread. Seguendo il suggerimento @morningsun,
% timeit numexpr.evaluate ('log (RRC)')
dà 5.6 ms, che è alla pari con MATLAB, grazie! numexpr è abilitato per MKL
Vettorizzazione e parallelizzazione. – IKavanagh
Questo è uno scenario tipico [SIMD] (https://en.wikipedia.org/wiki/SIMD). Esplora prima le tecniche di vettorizzazione sul codice C++. Ad esempio, prova [OpenMP] (http://openmp.org/wp/). –
Il compilatore C++ non può sganciare le chiamate log2(), quindi trascorre molto tempo a tenere traccia degli indici del ciclo. E come dice IKavanagh, MATLAB parallelizza il calcolo. Si potrebbe facilmente farlo con [OpenMP] (http://openmp.org/wp/). – YSC