Skip to content

Commit

Permalink
[tmva][pymva] Do not disable tensorflow eager execution on MacoS
Browse files Browse the repository at this point in the history
Disbaling it causes an interference with multiprocessing and a restart of the process after it is endeded. This fixes the timeout of the PyKeras tests on MacOS.

This commits apply also some small fixes/improvements  on the deletetion of some TMVA objects.
  • Loading branch information
lmoneta committed Sep 6, 2023
1 parent 879c228 commit dff89cf
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 18 deletions.
27 changes: 17 additions & 10 deletions tmva/pymva/src/MethodPyKeras.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ ClassImp(MethodPyKeras);
MethodPyKeras::MethodPyKeras(const TString &jobName, const TString &methodTitle, DataSetInfo &dsi, const TString &theOption)
: PyMethodBase(jobName, Types::kPyKeras, methodTitle, dsi, theOption) {
fNumEpochs = 10;
fNumThreads = 0;
fBatchSize = 100;
fVerbose = 1;
fContinueTraining = false;
Expand Down Expand Up @@ -380,23 +381,29 @@ void MethodPyKeras::SetupKerasModelForEval() {

// disable eager execution (model will evaluate > 100 faster)
// need to be done before loading the model
#ifndef R__MACOSX // problem siabling eager execution on Macos (conflict with multiprocessing)
if (fUseTFKeras){
PyRunString("tf.compat.v1.disable_eager_execution()","Failed to disable eager execution");
Log() << kINFO << "Disabled TF eager execution when evaluating model " << Endl;
}
#endif

SetupKerasModel(true);

// Init evaluation (needed for getMvaValue)
fVals.resize(fNVars); // holds values used for classification and regression
npy_intp dimsVals[2] = {(npy_intp)1, (npy_intp)fNVars};
PyArrayObject* pVals = (PyArrayObject*)PyArray_SimpleNewFromData(2, dimsVals, NPY_FLOAT, (void*)fVals.data());
PyDict_SetItemString(fLocalNS, "vals", (PyObject*)pVals);
if (fNVars > 0) {
fVals.resize(fNVars); // holds values used for classification and regression
npy_intp dimsVals[2] = {(npy_intp)1, (npy_intp)fNVars};
PyArrayObject* pVals = (PyArrayObject*)PyArray_SimpleNewFromData(2, dimsVals, NPY_FLOAT, (void*)fVals.data());
PyDict_SetItemString(fLocalNS, "vals", (PyObject*)pVals);
}
// setup output variables
fOutput.resize(fNOutputs); // holds classification probabilities or regression output
npy_intp dimsOutput[2] = {(npy_intp)1, (npy_intp)fNOutputs};
PyArrayObject* pOutput = (PyArrayObject*)PyArray_SimpleNewFromData(2, dimsOutput, NPY_FLOAT, (void*)fOutput.data());
PyDict_SetItemString(fLocalNS, "output", (PyObject*)pOutput);
if (fNOutputs > 0) {
fOutput.resize(fNOutputs); // holds classification probabilities or regression output
npy_intp dimsOutput[2] = {(npy_intp)1, (npy_intp)fNOutputs};
PyArrayObject* pOutput = (PyArrayObject*)PyArray_SimpleNewFromData(2, dimsOutput, NPY_FLOAT, (void*)fOutput.data());
PyDict_SetItemString(fLocalNS, "output", (PyObject*)pOutput);
}

fModelIsSetupForEval = true;
}
Expand Down Expand Up @@ -707,6 +714,7 @@ std::vector<Double_t> MethodPyKeras::GetMvaValues(Long64_t firstEvt, Long64_t la
}
}

std::vector<double> mvaValues(nEvents);
npy_intp dimsData[2] = {(npy_intp)nEvents, (npy_intp)fNVars};
PyArrayObject* pDataMvaValues = (PyArrayObject*)PyArray_SimpleNewFromData(2, dimsData, NPY_FLOAT, (void*)data);
if (pDataMvaValues==0) Log() << "Failed to load data to Python array" << Endl;
Expand All @@ -717,11 +725,10 @@ std::vector<Double_t> MethodPyKeras::GetMvaValues(Long64_t firstEvt, Long64_t la
PyArrayObject* pPredictions = (PyArrayObject*) PyObject_CallMethod(pModel, (char*)"predict", (char*)"O", pDataMvaValues);
if (pPredictions==0) Log() << kFATAL << "Failed to get predictions" << Endl;
delete[] data;

// Load predictions to double vector
// NOTE: The signal probability is given at the output
std::vector<double> mvaValues(nEvents);
float* predictionsData = (float*) PyArray_DATA(pPredictions);

for (UInt_t i=0; i<nEvents; i++) {
mvaValues[i] = (double) predictionsData[i*fNOutputs + TMVA::Types::kSignal];
}
Expand Down
5 changes: 4 additions & 1 deletion tmva/pymva/src/PyMethodBase.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,8 @@ PyMethodBase::PyMethodBase(Types::EMVA methodType,
PyMethodBase::~PyMethodBase()
{
// should we delete here fLocalNS ?
//PyFinalize();
if (fLocalNS) Py_DECREF(fLocalNS);
}

///////////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -321,6 +323,7 @@ Int_t PyMethodBase::UnSerialize(TString path, PyObject **obj)
/// Py_single_input, Py_file_input)

void PyMethodBase::PyRunString(TString code, TString errorMessage, int start) {
//std::cout << "Run: >> " << code << std::endl;
fPyReturn = PyRun_String(code, start, fGlobalNS, fLocalNS);
if (!fPyReturn) {
Log() << kWARNING << "Failed to run python code: " << code << Endl;
Expand Down Expand Up @@ -397,7 +400,7 @@ std::vector<size_t> PyMethodBase::GetDataFromList(PyObject* listObject){
}

//////////////////////////////////////////////////////////////////////////////////
/// \brief Utility function which checks if a given key is present in a Python
/// \brief Utility function which checks if a given key is present in a Python
/// dictionary object and returns the associated value or throws runtime
/// error. This is to replace PyDict_GetItemWithError in Python 2.
///
Expand Down
6 changes: 3 additions & 3 deletions tmva/tmva/src/DataSetInfo.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -85,10 +85,10 @@ TMVA::DataSetInfo::~DataSetInfo()
ClearDataSet();

for(UInt_t i=0, iEnd = fClasses.size(); i<iEnd; ++i) {
delete fClasses[i];
if (fClasses[i]) delete fClasses[i];
}

delete fTargetsForMulticlass;
if (fTargetsForMulticlass) delete fTargetsForMulticlass;

delete fLogger;
}
Expand All @@ -97,7 +97,7 @@ TMVA::DataSetInfo::~DataSetInfo()

void TMVA::DataSetInfo::ClearDataSet() const
{
if(fDataSet!=0) { delete fDataSet; fDataSet=0; }
if(fDataSet) { delete fDataSet; fDataSet=nullptr; }
}

////////////////////////////////////////////////////////////////////////////////
Expand Down
8 changes: 4 additions & 4 deletions tmva/tmva/src/MethodBase.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -364,7 +364,7 @@ TMVA::MethodBase::MethodBase( Types::EMVA methodType,
TMVA::MethodBase::~MethodBase( void )
{
// destructor
if (!fSetupCompleted) Log() << kFATAL <<Form("Dataset[%s] : ",DataInfo().GetName())<< "Calling destructor of method which got never setup" << Endl;
if (!fSetupCompleted) Log() << kWARNING <<Form("Dataset[%s] : ",DataInfo().GetName())<< "Calling destructor of method which got never setup" << Endl;

// destructor
if (fInputVars != 0) { fInputVars->clear(); delete fInputVars; }
Expand All @@ -385,14 +385,14 @@ TMVA::MethodBase::~MethodBase( void )
if (fSplTrainRefB) { delete fSplTrainRefB; fSplTrainRefB = 0; }
if (fSplTrainEffBvsS) { delete fSplTrainEffBvsS; fSplTrainEffBvsS = 0; }

for (Int_t i = 0; i < 2; i++ ) {
for (size_t i = 0; i < fEventCollections.size(); i++ ) {
if (fEventCollections.at(i)) {
for (std::vector<Event*>::const_iterator it = fEventCollections.at(i)->begin();
it != fEventCollections.at(i)->end(); ++it) {
delete (*it);
}
delete fEventCollections.at(i);
fEventCollections.at(i) = 0;
fEventCollections.at(i) = nullptr;
}
}

Expand Down Expand Up @@ -878,7 +878,7 @@ void TMVA::MethodBase::AddClassifierOutput( Types::ETreeType type )

// use timer
Timer timer( nEvents, GetName(), kTRUE );
std::vector<Double_t> mvaValues = GetMvaValues(0, nEvents, true);
std::vector<Double_t> mvaValues(nEvents);// = GetMvaValues(0, nEvents, true);

// store time used for testing
if (type==Types::kTesting)
Expand Down

0 comments on commit dff89cf

Please sign in to comment.