Contenu principal

Cette page a été traduite par traduction automatique. Cliquez ici pour voir la dernière version en anglais.

Tracé pendant le balayage des paramètres avec parfeval

Cet exemple montre comment effectuer un balayage de paramètres en parallèle avec parfeval et renvoyer les résultats pendant les calculs avec un objet DataQueue.

parfeval ne bloque pas MATLAB, vous pouvez donc continuer à travailler pendant que les calculs ont lieu.

L'exemple effectue un balayage de paramètres sur le système de Lorenz d'équations différentielles ordinaires, sur les paramètres σ et ρ, et montre la nature chaotique de ce système.

ddtx=σ(y-z)ddty=x(ρ-z)-yddtz=xy-βx

Configurer un environnement parallèle

Créez un pool de threads parallèles en utilisant la fonction parpool.

parpool("Threads");
Starting parallel pool (parpool) using the 'Threads' profile ...
Connected to parallel pool with 6 workers.

Créer une grille de paramètres

Définissez la plage de paramètres que vous souhaitez explorer dans le balayage des paramètres.

gridSize = 40;
sigma = linspace(5,45,gridSize);
rho = linspace(50,100,gridSize);
beta = 8/3;

Créez une grille 2D de paramètres en utilisant la fonction meshgrid.

[rho,sigma] = meshgrid(rho,sigma);

Effectuer un balayage des paramètres en parallèle

Après avoir défini les paramètres, vous pouvez effectuer le balayage des paramètres en parallèle.

Pour visualiser les résultats intermédiaires du balayage des paramètres, créez un graphique de surface. Notez que l'initialisation du composant Z de la surface avec NaN crée un tracé vide.

figure;
surface = surf(rho,sigma,NaN(size(sigma)));
xlabel('\rho','Interpreter','Tex')
ylabel('\sigma','Interpreter','Tex')

Pour envoyer des données intermédiaires à partir des workers, créez un objet DataQueue. Configurez une fonction qui met à jour le tracé de surface chaque fois qu'un worker envoie des données en utilisant la fonction afterEach. La fonction updatePlot est une fonction de support définie à la fin de l'exemple.

Q = parallel.pool.DataQueue;
afterEach(Q,@(data) updatePlot(surface,data));

parfeval fonctionne plus efficacement lorsque vous répartissez la charge de travail. Pour répartir la charge de travail, regroupez les paramètres à explorer dans des partitions. Pour cet exemple, divisez en partitions uniformes de taille step en utilisant l'opérateur deux points (:). Le tableau résultant partitions contient les limites des partitions. Notez que vous devez ajouter le point final de la dernière partition.

step = 100;
partitions = [1:step:numel(sigma),numel(sigma)+1]
partitions = 1×17

           1         101         201         301         401         501         601         701         801         901        1001        1101        1201        1301        1401        1501        1601

Pour de meilleures performances, essayez de diviser en partitions qui sont :

  • Assez grand pour que le temps de calcul soit important par rapport à la surcharge liée à la planification de la partition.

  • Assez petit pour qu'il y ait suffisamment de cloisons pour occuper tous les workers.

Pour représenter les exécutions de fonctions sur des workers parallèles et conserver leurs résultats, utilisez des objets futurs.

f(1:numel(partitions)-1) = parallel.FevalFuture;

Déchargez les calculs vers des workers parallèles en utilisant la fonction parfeval. parameterSweep est une fonction d'assistance définie à la fin de ce script qui résout le système de Lorenz sur une partition des paramètres à explorer. Il a un argument de sortie, vous devez donc spécifier 1 comme nombre de sorties dans parfeval.

for ii = 1:numel(partitions)-1
    f(ii) = parfeval(@parameterSweep,1,partitions(ii),partitions(ii+1),sigma,rho,beta,Q);
end

parfeval ne bloque pas MATLAB, vous pouvez donc continuer à travailler pendant que les calculs ont lieu. Les workers calculent en parallèle et envoient les résultats intermédiaires via le DataQueue dès qu'ils sont disponibles.

Si vous souhaitez bloquer MATLAB jusqu'à ce que parfeval soit terminé, utilisez la fonction wait sur les futurs objets. L'utilisation de la fonction wait est utile lorsque le code suivant dépend de la fin de parfeval.

wait(f);

Une fois que parfeval a terminé les calculs, wait termine et vous pouvez exécuter plus de code. Par exemple, tracez une sélection de solutions du système de Lorenz. Utilisez la fonction fetchOutputs pour récupérer les résultats stockés dans les objets futurs.

results = fetchOutputs(f);
idxs = randperm(numel(results),4);
figure
for n = 1:numel(idxs)
    nexttile
    a = results{idxs(n)};
    plot3(a(:,1),a(:,2),a(:,3))
    grid on
    xlabel("x")
    ylabel("y")
    zlabel("z")
    title("Lorenz System Solution", ...
        "\rho = "+ num2str(rho(idxs(n)),'%5.2f') + " \sigma = "+ num2str(sigma(idxs(n)),'%5.2f'),Interpreter="tex")
end

Si votre balayage de paramètres nécessite davantage de ressources de calcul et que vous avez accès à un cluster, vous pouvez augmenter vos calculs parfeval. Pour plus d'informations, voir Scale Up from Desktop to Cluster.

Définir les fonctions d'assistance

Définir une fonction d'aide qui résout le système de Lorenz sur une partition des paramètres à explorer. Envoyez les résultats intermédiaires au client MATLAB en utilisant la fonction send sur l'objet DataQueue.

function results = parameterSweep(first,last,sigma,rho,beta,Q)
    results = cell(last-first,1);
    for ii = first:last-1
        lorenzSystem = @(t,a) [sigma(ii)*(a(2) - a(1)); a(1)*(rho(ii) - a(3)) - a(2); a(1)*a(2) - beta*a(3)];
        [t,a] = ode45(lorenzSystem,[0 100],[1 1 1]);
        send(Q,[ii,a(end,3)]);
        results{ii-first+1} = a;
    end
end

Définissez une autre fonction d’assistance qui met à jour le tracé de surface lorsque de nouvelles données arrivent.

function updatePlot(surface,data)
    surface.ZData(data(1)) = data(2);
    drawnow('limitrate');
end

Voir aussi

| | |

Rubriques