Voici une question intéressante pour les codeurs parmi nous.
J'ai deux versions d'une simulation que j'exécute. L'algorithme est identique, à l'exception de l'exécution de l'un en utilisant une boucle For Each() et de l'autre en exécutant Parallel Assign. La boucle For Each prend systématiquement beaucoup moins de temps pour effectuer le même ensemble de calculs que Parallel Assign, même avec mes 8 cœurs au maximum.

Quelqu'un a-t-il une idée de la raison pour laquelle cela pourrait être le cas ? Le code de chaque version de la simulation est ci-dessous :
Version d'attribution parallèle
// JSL Code for Simulation of Harmonized Compendial Dissolution Criteria USP <711>
// Simulation function for USP dissolution - three stage test
// reps = number of simulated lots for simulation
// mean = the process mean
// sd = the process standard deviation
// Q = value as specified in the mongraph for the product
//
// Summary Matrix Key
// ==================
// 1 "PassS1"
// 2 "PassS2"
// 3 "PassS3"
// 4 "#<Q s1="">= Q & sum_matrix[i, 7] == 0,
sum_matrix[i, 2] = 1;
sum_matrix[i, 12] = 1;
sum_matrix[i, 14] = 0;
,
sum_matrix[i, 2] = 0;
If( sum_matrix[i, 7] <= 2 & sum_matrix[i, 8] == 0,
sum_matrix[i, 14] = 1,
sum_matrix[i, 14] = 0;
sum_matrix[i, 12] = 0;
);
)
);
// Stage 3
If( sum_matrix[i, 14] == 1,
If( sum_matrix[i, 9] >= Q & sum_matrix[i, 10] <= 2 & sum_matrix[i, 11] == 0,
sum_matrix[i, 3] = 1;
sum_matrix[i, 12] = 1;
,
sum_matrix[i, 3] = 0;
sum_matrix[i, 12] = 0;
)
);
);
// return the value
Mean( sum_matrix[0, 12] );
)},
simMat[a, b] = simDissoTest( repN, 80 + cs[1] + cs[3] * (b - 1), a * rs[3] )
);
stop = Tick Seconds();
time = stopWatch( start, stop, "min" );
Show( time, ntests );</Q>
Pour chaque version ()
// JSL Code for Simulation of Harmonized Compendial Dissolution Criteria USP <711>
// Simulation function for USP dissolution - three stage test
// reps = number of simulated lots for simulation
// mean = the process mean
// sd = the process standard deviation
// Q = value as specified in the mongraph for the product
//
// Summary Matrix Key
// ==================
// 1 "PassS1"
// 2 "PassS2"
// 3 "PassS3"
// 4 "#<Q s1="">= Q & sum_matrix[i, 7] == 0,
sum_matrix[i, 2] = 1;
sum_matrix[i, 12] = 1;
sum_matrix[i, 14] = 0;
,
sum_matrix[i, 2] = 0;
If( sum_matrix[i, 7] <= 2 & sum_matrix[i, 8] == 0,
sum_matrix[i, 14] = 1,
sum_matrix[i, 14] = 0;
sum_matrix[i, 12] = 0;
);
)
);
// Stage 3
If( sum_matrix[i, 14] == 1,
If( sum_matrix[i, 9] >= Q & sum_matrix[i, 10] <= 2 & sum_matrix[i, 11] == 0,
sum_matrix[i, 3] = 1;
sum_matrix[i, 12] = 1;
,
sum_matrix[i, 3] = 0;
sum_matrix[i, 12] = 0;
)
);
);
// return the value
Mean( sum_matrix[0, 12] );
);
//---------------------------------------------------------------------------------
// Parallelized Simulation
//---------------------------------------------------------------------------------
// define the size of the matrix ans the step size
rows = vecSize( 0.1, 12, 0.1 );
rowShape = [0.1, 12, 0.1];
cols = vecSize( -1, 10, 0.5 );
colShape = [-1, 10, 0.5];
reps = 100;
ntests = rows * cols;
//create the Parallel test matrix
simMat = J( rows, cols, Empty() );
// run the simulation (testing scalability)
//New Window( "test", lb = Lineup Box( N Col( 2 ) ) );
/*For Each( {repN, i}, {1, 50, 100, 500},
start = Tick Seconds();
For Each( {v, {i, j}}, simMat,
simMat[i, j] = simDissoTest( repN, 80 + colShape[1] + colShape[3] * (j - 1), i * rowShape[3] )
);
stop = Tick Seconds();
time = stopWatch( start, stop, "min" );
Show( repN, time, ntests );
//lb << Append( V List Box( Text Box( "Number of reps: " || Char( repN ) ), New Heat Image( simMat ) ) );
);*/
// run the simulation
start = Tick Seconds();
For Each( {v, {i, j}}, simMat,
simMat[i, j] = simDissoTest( reps, 80 + colShape[1] + colShape[3] * (j - 1), i * rowShape[3] )
);
stop = Tick Seconds();
time = stopWatch( start, stop, "min" );
Show( reps, time, ntests );
// make the data table from the matrix
tallMatrix = J( ntests, 3, Empty() );
k = 1; // an indexer
For Each( {v, {i, j}}, simMat,
tallMatrix[k, 1] = 80 + colShape[1] + colShape[3] * (j - 1);
tallMatrix[k, 2] = i * rowShape[3];
tallMatrix[k, 3] = v;
k++;
);
dt = As Table( tallMatrix );
Column( dt, 1 ) << Set Name( "Mean" );
Column( dt, 2 ) << Set Name( "Std Dev" );
Column( dt, 3 ) << Set Name( "Pass Rate" );
dt << New Script(
"Graph",
Graph Builder(
Size( 742, 817 ),
Show Control Panel( 0 ),
Fit to Window,
Variables( X( :Mean ), Y( :Std Dev ), Color( :Pass Rate ) ),
Elements( Contour( X, Y, Legend( 6 ), Number of Levels( 5 ), Smoothness( 0.146217717445672 ) ) ),
SendToReport(
Dispatch(
{},
"Mean",
ScaleBox,
{Min( 79.0036098075223 ), Max( 89.9788461538462 ), Inc( 2 ), Minor Ticks( 1 )}
),
Dispatch(
{},
"Std Dev",
ScaleBox,
{Min( 0.0888646043293861 ), Max( 11.971158234127 ), Inc( 2 ), Minor Ticks( 1 )}
),
Dispatch(
{},
"400",
ScaleBox,
{Legend Model(
6,
Properties(
0,
{gradient(
{Color Theme( "Green Yellow Red"(1) ), Scale Values( [0.8 .] ),
Reverse Gradient( 1 )}
)},
Item ID( "Pass Rate", 1 )
)
)}
)
)
)
);
dt << Run Script("Graph");
disclaimer;</Q>Salut Mike,
J'avoue n'avoir fait qu'une analyse rapide du code, mais spécifiez-vous 1 000 répétitions pour la version parallèle et seulement 100 répétitions pour la version For Each ? (Bien que la fonction soit par défaut de 100 répétitions, il semble que vous en poussiez 1 000 vers la version parallèle en raison de la ligne 58.)
Lorsque j'ai utilisé les lignes 58 et 321 pour spécifier 1, 10 et 100 répétitions (je n'ai pas la patience pour 1000, désolé), les résultats étaient similaires à 1 et 10, mais le parallèle était plus rapide à 100.
Cela me semble raisonnable, car tout gain d'efficacité ne permettra de surmonter la surcharge de la configuration des threads parallèles qu'une fois que la tâche deviendra suffisamment importante.
-Brady