Aquí hay una pregunta interesante para los programadores entre nosotros.
Tengo dos tipos de simulación que estoy ejecutando. El algoritmo es idéntico, aparte de ejecutar uno usando un bucle For Each() y el otro ejecutando Parallel Assign. El bucle For Each siempre toma mucho menos tiempo para realizar el mismo conjunto de cálculos que la asignación paralela, incluso con mis 8 núcleos al máximo.

¿Alguien tiene alguna idea de por qué podría ser eso? El código para cada versión de la simulación se encuentra a continuación:
Versión de asignación paralela
// 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>
Para cada () versión
// 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>Hola Mike,
Confieso que solo hice un escaneo rápido del código, pero ¿estás especificando 1000 repeticiones para la versión paralela y solo 100 repeticiones para la versión Para Cada? (Aunque la función tiene por defecto 100 repeticiones, parece que estás empujando 1000 a la versión paralela debido a la línea 58).
Cuando usé las líneas 58 y 321 para especificar 1, 10 y 100 repeticiones (no tengo paciencia para 1000, lo siento), los resultados fueron similares en 1 y 10, pero el paralelo fue más rápido en 100.
Esto me parece razonable, ya que cualquier ganancia en eficiencia sólo superará la sobrecarga de la configuración de subprocesos paralelos una vez que la tarea sea lo suficientemente grande.
-Brady