2017-10-17 5 views
-1

J'ai besoin de générer des nombres aléatoires uniformes dans une boucle for. pour la boucle va pour les numéros de 1000000. Il y en a une autre pour boucle qui va à 2000 à l'intérieur. Donc, je génère 2 * 10^9 nombres aléatoires uniformes. J'utilise la méthode ci-dessous:Quelle est la méthode la plus rapide pour créer des nombres aléatoires uniformes en C++?

#include <random> 
    double zeta; 
    unsigned seed = std::chrono::system_clock::now().time_since_epoch().count(); 
     auto uniform_rand = bind(uniform_real_distribution<double>(0,1), mt19937(seed)); 
    for(int j=0; j<1000000; j++) 
       for(int i=0; i<2000; i++) 
     zeta=-eta/2.0+uniform_rand()*eta; // in the range (-eta/2, +eta/2) 
theta[i]+=zeta; 
    end 
end 
+4

'std :: bind' a tendance à être surclassé par lambdas, à la fois en termes de lisibilité et de performance. – chris

+4

C'est énormément de nombres aléatoires. Si vous en avez besoin de beaucoup, pourquoi ne pas le découper en threads pour utiliser plusieurs cœurs? – tadman

+0

Désolé, je ne pouvais pas comprendre ce que vous voulez dire @tadman –

Répondre

1

C'est presque le même que le vôtre. Je ne vois tout simplement pas besoin d'un liant ou d'un lambda.

EDIT: J'ai aussi changé le générateur mt19937-minstd_rand qui a fait le code 88 fois plus rapide. Avec mt19937 le code a approximativement la même performance que celle de la question.

#include <random> 

int main() { 
    /*std::mt19937 gen(std::random_device{}());*/ 
    // Changing mt19937 to minstd_rand makes the code run 88 times faster! 
    std::minstd_rand gen(std::random_device{}()); 
    std::uniform_real_distribution<double> dist(0, 1); 
    for(unsigned int i = 0; i < 1000000; ++i) { 
     for(unsigned int j = 0; j < 2000; ++j) { 
      double anotherRandomNumber = dist(gen); 
      // Do whatever you want with generated random number. 
     } 
    } 
} 
+0

Est-ce vraiment plus rapide que ce que j'ai écrit? –

+0

Crée-t-il différents nombres aléatoires dans différentes exécutions? –

+0

@OliverRange oui, il ensemence le générateur aléatoire à chaque fois avec 'std :: random_device'. Mais parfois cela ne fonctionnera pas, voir https://stackoverflow.com/questions/18880654/why-do-i-get-the-same-sequence-for-every-run-with-stdrandom-device-with-mingw –

0

Utilisez cet algorithme de here:

uint64_t s[2] = { 0x41, 0x29837592 }; 

static inline uint64_t rotl(const uint64_t x, int k) { 
    return (x << k) | (x >> (64 - k)); 
} 

uint64_t next(void) { 
    const uint64_t s0 = s[0]; 
    uint64_t s1 = s[1]; 
    const uint64_t result = s0 + s1; 

    s1 ^= s0; 
    s[0] = rotl(s0, 55)^s1^(s1 << 14); // a, b 
    s[1] = rotl(s1, 36); // c 

    return result; 
} 

double uniform() { 
    return next()*(1.0/18446744073709551616.0); 
} 

C'est 4 fois plus vite que votre exemple sur ma machine.

Remarque: vous devez semer s, éventuellement avec std::random_device.

+0

Pourriez-vous s'il vous plaît fournir une réponse qui utilise pour boucle comme mon cas? –

+0

@OliverRange: collez ce code dans le vôtre et remplacez uniform_rand() 'par uniform()'. – geza

+0

Je ne sais pas où le poster. après principal et avant pour la boucle? –