Hallo JMP-Community,
In meinen JSL-Skripten generiere ich oft nacheinander neue Spalten, etwa so:
...
DT << New Column( "Some Name1", Numeric, "Continuous", Formula( Some Formula1 ) );
DT << New Column( "Some Name2", Numeric, "Continuous", Formula( Some Formula2 ) );
DT << New Column( "Some Name3", Numeric, "Continuous", Formula( Some Formula3 ) );
...
Meine Datentabellen sind üblicherweise sehr groß und können bis zu 100 Millionen Zeilen umfassen. Die verwendeten Formeln beinhalten oft statistische Funktionen wie Spaltenmittelwert() , Spaltenmaximum() usw., wodurch die Berechnung mit zunehmender Zeilenanzahl immer langsamer wird. Es kann vorkommen, dass einige neue Spalten voneinander abhängen, bitte gehen Sie aber vorerst davon aus, dass dies nicht der Fall ist.
Bei der Auswertung meines Skripts stelle ich fest, dass JMP 19.1 nur 3-4 % meiner CPU (16 Kerne, 32 Threads) nutzt.
Lässt sich die Berechnung beschleunigen, z. B. durch Parallelisierung, ohne Teilmengen zu erstellen und deren Ergebnisse anschließend wieder zusammenzuführen? Kann ich mit JSL in JMP parallel an ein und derselben Datentabelle arbeiten?
Falls nicht, halten Sie den Ansatz „Teilmengenformel berechnen und wieder zusammenführen“ für einen Versuch wert?
Prost
Rauben
Je nach Art Ihrer Berechnung (und ob Sie Formeln benötigen oder nicht), könnten Sie gegebenenfalls eine Zusammenfassungstabelle erstellen, dort Berechnungen durchführen und diese anschließend wieder in Ihre Tabelle eintragen.
Es gibt ein Tool zur Verwaltung der Parallelisierung von Matrizen: Parallel Assign.
Ich bin nicht überzeugt, dass dies die Sache tatsächlich beschleunigen wird, es sei denn, Sie erstellen viele neue Spalten auf der Grundlage einer kleinen Anzahl von Eingabespalten und sind in der Auswahl der Funktionen, die Sie verwenden, sehr eingeschränkt.
Hier ein Beispiel:
Names default to here(1);
dt = Open("$Sample_data/Pollen.jmp");
//first a simple demo of parallel assign to calculate column means
moutmeans = J(n col(dt), 1, .); //blank matrix that will be populated
mdata = dt << get as matrix; //input data as a matrix
Parallel Assign(
{ mdata = mdata }, //variables needed in the 'worker thread'
moutmeans[a, b] = mean(mdata[0,a]); //this fills in one cell
);
show(moutmeans); //col means are here
// Now for new columns
//mdata = mdata[1::2,0]; //a way to start small if you add show()
nrows = nrow(mdata);
cnames = dt << get column names(); //used to find position of columns in matrix
// Write formulas for each columns using column names as placeholders
// to be replaced by matrix values later, this would work for pretty simple logic
formulas = Eval List({
Expr(edge + nub + 10),
Eval Expr(nub - Expr( col mean(dt:nub) ) ) //note this col mean evaluates now
});
newcnames = {"a","b"}; //new column names used later
mout = J(nrows, length(formulas), .); //empty matrix to populate
Parallel Assign(
{
mdata = mdata,
formulas = formulas,
cnames = cnames
},
mout[a, b] = (
f = formulas[b];
//assign values to all potential variables used in matricies
//(bad idea if lots of unused columns)
for(i=1, i<= n items(cnames), i++,
//Make a list with the variable to assign and value to assign it to,
// then replace the list with assign
Eval( Substitute(
Eval List( {as name( name expr( cnames[i] ) ), mdata[a,i]} ),
Expr({}),
Expr( assign() )
) );
);
eval(f);
);
);
//put new columns in table
for each({c,i}, newcnames, dt << New Column(c,Numeric,Continuous, << Set Values(mout[0,i])));
//add columns to double check it worked
dt << New Column("a-check", Numeric, "Continuous", Format("Best", 12), Formula(:edge + :nub + 10));
dt << New Column("b-check", Numeric, "Continuous", Format("Best", 12), Formula(:nub - Col Mean(:nub)));
Sie könnten versuchen, die Formelauswertung zu unterdrücken, bis alle Spalten erstellt wurden, und dann „Formeln ausführen“ verwenden.
( @Ryan_Gilmore , @Robbbb ) dt<
Hier ist ein Punkt auf Ihrer Wunschliste, für den Sie abstimmen können.
Hintergrundformelbewertung