Ho scritto i seguenti codici in R e C++ che eseguono lo stesso algoritmo:Perché il mio codice C++ è molto più lento di R?
a) Per simulare la variabile casuale X 500 volte. (X ha valore 0.9 con prob 0.5 e 1.1 con prob 0.5)
b) Moltiplica questi 500 valori simulati insieme per ottenere un valore. Salvare il valore in un contenitore
c) Ripetere 10000000 volte in modo che il contenitore ha 10000000 valori
R:
ptm <- proc.time()
steps <- 500
MCsize <- 10000000
a <- rbinom(MCsize,steps,0.5)
b <- rep(500,times=MCsize) - a
result <- rep(1.1,times=MCsize)^a*rep(0.9,times=MCsize)^b
proc.time()-ptm
C++
#include <numeric>
#include <vector>
#include <iostream>
#include <random>
#include <thread>
#include <mutex>
#include <cmath>
#include <algorithm>
#include <chrono>
const size_t MCsize = 10000000;
std::mutex mutex1;
std::mutex mutex2;
unsigned seed_;
std::vector<double> cache;
void generatereturns(size_t steps, int RUNS){
mutex2.lock();
// setting seed
try{
std::mt19937 tmpgenerator(seed_);
seed_ = tmpgenerator();
std::cout << "SEED : " << seed_ << std::endl;
}catch(int exception){
mutex2.unlock();
}
mutex2.unlock();
// Creating generator
std::binomial_distribution<int> distribution(steps,0.5);
std::mt19937 generator(seed_);
for(int i = 0; i!= RUNS; ++i){
double power;
double returns;
power = distribution(generator);
returns = pow(0.9,power) * pow(1.1,(double)steps - power);
std::lock_guard<std::mutex> guard(mutex1);
cache.push_back(returns);
}
}
int main(){
std::chrono::steady_clock::time_point start = std::chrono::steady_clock::now();
size_t steps = 500;
seed_ = 777;
unsigned concurentThreadsSupported = std::max(std::thread::hardware_concurrency(),(unsigned)1);
int remainder = MCsize % concurentThreadsSupported;
std::vector<std::thread> threads;
// starting sub-thread simulations
if(concurentThreadsSupported != 1){
for(int i = 0 ; i != concurentThreadsSupported - 1; ++i){
if(remainder != 0){
threads.push_back(std::thread(generatereturns,steps,MCsize/ concurentThreadsSupported + 1));
remainder--;
}else{
threads.push_back(std::thread(generatereturns,steps,MCsize/ concurentThreadsSupported));
}
}
}
//starting main thread simulation
if(remainder != 0){
generatereturns(steps, MCsize/concurentThreadsSupported + 1);
remainder--;
}else{
generatereturns(steps, MCsize/concurentThreadsSupported);
}
for (auto& th : threads) th.join();
std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now() ;
typedef std::chrono::duration<int,std::milli> millisecs_t ;
millisecs_t duration(std::chrono::duration_cast<millisecs_t>(end-start)) ;
std::cout << "Time elapsed : " << duration.count() << " milliseconds.\n" ;
return 0;
}
non riesco a capire perché il mio Il codice R è molto più veloce del mio codice C++ (3.29s vs 12s) anche se ho usato quattro thread nel codice C++? Qualcuno può illuminarmi per favore? Come dovrei migliorare il mio codice C++ per farlo funzionare più velocemente?
MODIFICA:
Grazie per tutti i consigli! Ho riservato capacità per i miei vettori e ridotto la quantità di blocchi nel mio codice. L'aggiornamento cruciale nelle generatereturns() è:
std::vector<double> cache(MCsize);
std::vector<double>::iterator currit = cache.begin();
//.....
// Creating generator
std::binomial_distribution<int> distribution(steps,0.5);
std::mt19937 generator(seed_);
std::vector<double> tmpvec(RUNS);
for(int i = 0; i!= RUNS; ++i){
double power;
double returns;
power = distribution(generator);
returns = pow(0.9,power) * pow(1.1,(double)steps - power);
tmpvec[i] = returns;
}
std::lock_guard<std::mutex> guard(mutex1);
std::move(tmpvec.begin(),tmpvec.end(),currit);
currit += RUNS;
Invece di bloccaggio ogni volta, ho creato un vettore temporaneo e poi utilizzato std :: mossa per spostare gli elementi che tempvec nella cache. Ora il tempo trascorso è ridotto a 1,9 secondi.
compilatore? OS?impostazioni del compilatore? macchina? Siamo spiacenti, non ci sono informazioni per noi! – Klaus
Sembra che si stia facendo un eccessivo blocco nel codice. Hai provato una versione senza thread, prima? In caso contrario, dovresti provare a scrivere l'output su vettori separati <> che non devono essere bloccati, combinando l'output alla fine. Prova anche a riservare capacità per i tuoi vettori. –
Uso Visual Studio Express con Windows 8. Il mio processore è Intel i5 con quadcore. – user22119