Simulation Parallèle

Postez ici vos questions, réponses, commentaires ou suggestions - Les sujets seront ultérieurement répartis dans les archives par les modérateurs

Modérateur : Groupe des modérateurs

Jérémy PEROMET
Messages : 4
Enregistré le : 29 Aoû 2018, 12:27

Simulation Parallèle

Messagepar Jérémy PEROMET » 14 Sep 2018, 10:29

Bonjour,

J'effectue actuellement des simulations et du calcul stochastique en grande quantité. Je fais des boucles for pour remplir une matrice dont le nombre de ligne est le nombre simulations et le nombre de colonne est le nombre de projection.
Voici un exemple simple des fonctions que j'utilise :

Code : Tout sélectionner

# Simulation d'un processus de poisson d'intensite lambda dans [0,n]
# La fonction nous renvoie une matrice avec la premiere colonne qui contient les Tt et en deuxieme colonne les Nt.
simpois=function(n,lambda,graine){
  # n : borne superieure pour le parametre du temps
  # lambda : intensite du processus de poisson
  if (n<0){return('Le parametre n doit etre positif !')}
  else {
    if (lambda<=0){return('Le parametre lambda doit etre strictement positif !')}
    else {
      Tt=0
      Nt=0
      set.seed(seed = graine)
      while(Tt[length(Tt)]<n){
        Tt=c(Tt,Tt[length(Tt)]+rexp(1,lambda))
        Nt=c(Nt,Nt[length(Nt)]+1)
      }
      # Ici on corrige les erreurs qui sont faites sur la fin car
      # la trajectoire ne s'arrete pas direct a n
      Tt[length(Tt)]=n
      return( cbind(Tt,Nt) )
    }
  }
}
FunSaut=function(N,n,lambda,moy,vol){
saut=matrix(0,nrow=N,ncol=n)
  for (i3 in 1:N) {
  # Simulation d'un processus de poisson de parametre lambda dans [0,1]
  SP=simpois(n+10,lambda,i3) # On simule un processus sur une periode plus grande
  Tt=SP[,1]
  Nt=SP[,2]
  # on recupere les Valeurs de Nt lorsque t=0,1,...
  pos=rep(0,n+1)
  for( l in 1:(n+1)){
    pos[l]=length(Tt[Tt<=(l-1)])
  }
 
  # On fait la difference afin de savoir combien de loi normale qu'il faut simuler
  saut[i3,]=diff(Nt[pos])
   
  }
rm(.Random.seed, envir=globalenv())
# Creation de la matrice qui nous permet de simuler la hauteur des sauts
a=matrix(data = 0,nrow = N,ncol = n)
for (i2 in 1:N){
  # On va mettre dans a la somme des loi normale qu'il faut simuler
  # pour passer de l'instant i a i+1
  for (u in 1:n) {
    if ((saut[i2,u])>0){
      for ( j in 1:(saut[i2,u])){
        a[i2,u]=a[i2,u]+rnorm(1,mean = moy, sd = vol)
      }
    }
  }
}
return(a)
}


Donc ici le code nous retourne une matrice de sauts gaussiens.

J'aimerais paralléliser ce programme avec pour idée de simuler, par exemple, 1000 lignes par coeur virtuel x 8 coeurs au lieu de 8000 lignes sur 1 seul coeur..

J'ai lu beaucoup de choses (sur les packages parallel, doParallel, Foreach,etc.) mais je n'arrive pas à adapter mon programme, puisque je rempli et retourne une matrice et non un simple vecteur dont je voudrais la moyenne (par exemple)..

Merci par avance de l'intérêt porté à ma demande d'aide.

Bien à vous

Jérémy

Logez Maxime
Messages : 2823
Enregistré le : 26 Sep 2006, 11:35

Re: Simulation Parallèle

Messagepar Logez Maxime » 14 Sep 2018, 14:46

Bonjour,

Si j'ai bien compris tu remplis des lignes de matrice. Si tes lignes sont indépendantes alors tu peux très bien en remplir 1000 par coeur et ensuite les lier avec un rbind. Après tu as différentes possibilités selon l'OS sur lequel tu es. Sous windows c'est des clusters de type SOCK (a memoire non partagé) alors que linux et macOs tu peux aussi avoir des clusters de type FORK a memoire partagé. Avec les SOCK tu devras exporter tous les objets dont tu aurais besoin dans ton calcul sur chaque coeur, alors que tu n'as pas à faire ça avec les FORK.

A titre personnel j'utilise soit la librairie parallel soit doSNOW.
Un exemple pour des matrices :

Code : Tout sélectionner

library(parallel)
cl <- makeCluster(4, "SOCK") # cluster sock 4 coeurs
f1 <- function(n) {
  mat <- matrix(numeric(), n, 100)
  for (i in 1:n) {
    for (j in 1:100) {
      if (j ==1){
        mat[i,j] <- 1
        }else{
          mat[i,j] <- rnorm(1, mat[i,j-1])
        }
      }
    }
    mat
    }
 # pour une matrice de 8000 normale tu mets n = 8000
 # en parallel
 res <- parLapply(cl, rep(1000,8), f1)
 stopCluster(cl)
 str(res)
List of 8
 $ : num [1:1000, 1:100] 1 1 1 1 1 1 1 1 1 1 ...
 $ : num [1:1000, 1:100] 1 1 1 1 1 1 1 1 1 1 ...
 $ : num [1:1000, 1:100] 1 1 1 1 1 1 1 1 1 1 ...
 $ : num [1:1000, 1:100] 1 1 1 1 1 1 1 1 1 1 ...
 $ : num [1:1000, 1:100] 1 1 1 1 1 1 1 1 1 1 ...
 $ : num [1:1000, 1:100] 1 1 1 1 1 1 1 1 1 1 ...
 $ : num [1:1000, 1:100] 1 1 1 1 1 1 1 1 1 1 ...
 $ : num [1:1000, 1:100] 1 1 1 1 1 1 1 1 1 1 ...
 # une liste de 8 matrices de 1000 lignes
 res <- do.call(rbind, res)
 str(res)
 num [1:8000, 1:100] 1 1 1 1 1 1 1 1 1 1 ...
 # une matrice de 8000 lignes
Ce n'est qu'un exemple parmi d'autres pour t'aider a paralléliser ton calcul.

Après ton code peut surement être simplifié. Je ne suis pas sur par exemple que tu as besoin de la dernière boucle.
Au lieu de for (j in 1:saut[i2,u])) a[i2,u]=a[i2,u]+rnorm(1,mean = moy, sd = vol) tu dois pouvoir écrire ai[i2,u] <- ai[i2,u]+sum(rnorm(saut[i2,u]), moy, sd).
D'autres simplifications doivent pouvoir être faites.
Cordialement,
Maxime

Jérémy PEROMET
Messages : 4
Enregistré le : 29 Aoû 2018, 12:27

Re: Simulation Parallèle

Messagepar Jérémy PEROMET » 17 Sep 2018, 11:30

Bonjour,

En effet, il y a des optimisations possibles dans le code. En tout cas, merci beaucoup pour cette réponse qui va m'être très utile!

Bien cordialement


Retourner vers « Questions en cours »

Qui est en ligne

Utilisateurs parcourant ce forum : Aucun utilisateur enregistré et 1 invité