Salome HOME
Workload manager: more tests and other improvements.
authorOvidiu Mircescu <ovidiu.mircescu@edf.fr>
Thu, 4 Jun 2020 15:09:18 +0000 (17:09 +0200)
committerOvidiu Mircescu <ovidiu.mircescu@edf.fr>
Thu, 4 Jun 2020 15:09:18 +0000 (17:09 +0200)
15 files changed:
src/engine/Container.cxx
src/engine/Container.hxx
src/engine/Executor.cxx
src/genericgui/FormAdvParamContainer.cxx
src/genericgui/FormAdvParamContainer.hxx
src/genericgui/FormAdvParamContainer.ui
src/genericgui/FormContainer.cxx
src/genericgui/FormContainer.hxx
src/genericgui/FormParamContainer.ui
src/runtime/PythonNode.cxx
src/runtime/PythonNode.hxx
src/yacsloader/samples/wlm_2foreach_with_cache.xml [new file with mode: 0644]
src/yacsloader_swig/Test/runUnitTest.sh
src/yacsloader_swig/Test/testPynodeWithCache.py
src/yacsloader_swig/Test/testWorkloadManager.py

index 2843aa57466ed599f724913f0bac9af9c831b181..c560739d36b719d8578a5c6a33690dcf627c69fa 100644 (file)
@@ -32,7 +32,7 @@ const char Container::KIND_ENTRY[]="container_kind";
 
 const char Container::AOC_ENTRY[]="attached_on_cloning";
 
-const char Container::STORE_CONTEXT_PROPERTY[]="store_context";
+const char Container::USE_PYCACHE_PROPERTY[]="use_py_cache";
 
 Container::Container():_isAttachedOnCloning(false),_proc(0)
 {
@@ -106,11 +106,11 @@ void Container::setProperties(const std::map<std::string,std::string>& propertie
     setProperty((*it).first,(*it).second);
 }
 
-bool Container::storeContext()
+bool Container::isUsingPythonCache()
 {
   bool found = false;
   std::string str_value;
-  str_value = getProperty(STORE_CONTEXT_PROPERTY);
+  str_value = getProperty(USE_PYCACHE_PROPERTY);
   const char* yes_values[] = {"YES", "Yes", "yes", "TRUE", "True", "true", "1",
                               "ON", "on", "On"};
   for(const char* v : yes_values)
@@ -122,11 +122,11 @@ bool Container::storeContext()
   return found;
 }
 
-void Container::setStoreContext(bool v)
+void Container::usePythonCache(bool v)
 {
   if(v)
-    setProperty(STORE_CONTEXT_PROPERTY, "1");
+    setProperty(USE_PYCACHE_PROPERTY, "1");
   else
-    setProperty(STORE_CONTEXT_PROPERTY, "0");
+    setProperty(USE_PYCACHE_PROPERTY, "0");
 }
 
index 4f94da39051691951c61744e34d68ba2e48ad977..d2cd8d4856fdffd8de5b640e4541e23b8822960b 100644 (file)
@@ -55,8 +55,8 @@ namespace YACS
                          const std::string& resource_name,
                          const std::string& container_name);
       virtual bool canAcceptImposedResource();
-      virtual bool storeContext();
-      virtual void setStoreContext(bool v);
+      virtual bool isUsingPythonCache();
+      virtual void usePythonCache(bool v);
       virtual std::string getPlacementId(const Task *askingNode) const = 0;
       virtual std::string getFullPlacementId(const Task *askingNode) const = 0;
       //Edition only methods
@@ -86,7 +86,7 @@ namespace YACS
       virtual void shutdown(int level) = 0;
       static const char KIND_ENTRY[];
       static const char AOC_ENTRY[];
-      static const char STORE_CONTEXT_PROPERTY[];
+      static const char USE_PYCACHE_PROPERTY[];
     protected:
       std::string _name;
       mutable bool _isAttachedOnCloning;
index c46ebf2e8a9affb3644b60b6b3ac9db462059783..24603ef0af736d3e0199ac0ac4b234bb18298032 100644 (file)
@@ -1419,8 +1419,7 @@ void Executor::loadTask(Task *task, const WorkloadManager::RunInfo& runInfo)
   try
     {
       std::ostringstream container_name;
-      container_name << runInfo.resource.name << "-"
-                     << runInfo.type.name << "-" << runInfo.index;
+      container_name << runInfo.type.name << "-" << runInfo.index;
       task->imposeResource(runInfo.resource.name, container_name.str());
       traceExec(task, "load", ComputePlacement(task));
       task->load();
index c88a2790190f54c23bd11389d66038b71fbc4f38..935828299a945e3bb8f0551398060cc8e7a6f6f0 100644 (file)
@@ -64,6 +64,7 @@ FormAdvParamContainer::FormAdvParamContainer(std::map<std::string, std::string>&
   connect(sb_procNode, SIGNAL(valueChanged(const QString&)), this, SLOT(onModifyProcs(const QString&)));
   connect(sb_nbprocpar, SIGNAL(valueChanged(const QString&)), this, SLOT(onModifyProcPar(const QString&)));
   connect(sb_nbproc, SIGNAL(valueChanged(const QString&)), this, SLOT(onModifyProcRes(const QString&)));
+  connect(ch_pycache,SIGNAL(stateChanged(int)),this,SLOT(onModifyUsePyCache(int)));
 }
 
 FormAdvParamContainer::~FormAdvParamContainer()
@@ -113,6 +114,11 @@ void FormAdvParamContainer::FillPanel(const std::string& resource, YACS::ENGINE:
   else
     le_workdir->setText("");
 
+  if(_container)
+    ch_pycache->setCheckState(_container->isUsingPythonCache()?Qt::Checked:Qt::Unchecked);
+  else
+    ch_pycache->setCheckState(Qt::Unchecked);
+
   if(_properties.count("container_name"))
     le_contname->setText(_properties["container_name"].c_str());
   else
@@ -532,3 +538,20 @@ void FormAdvParamContainer::onModifyResourceList(const QString &text)
   if (properties["resource_list"] != text.toStdString())
     onModified();
 }
+
+void FormAdvParamContainer::onModifyUsePyCache(int val)
+{
+  if (!_container)
+    return;
+  bool val2(false);
+  if(val==Qt::Unchecked)
+    val2=false;
+  if(val==Qt::Checked)
+    val2=true;
+  bool prop = _container->isUsingPythonCache();
+  int prop2((int)val2);
+  std::ostringstream oss; oss << prop2;
+  _container->usePythonCache(val2);
+  if(prop!=val2)
+    onModified();
+}
index 3fba141c3a5e18191c8c548b528cd1eab57956a9..88e00f2b07ba54b37add8cc72ec592417b4e5b58 100644 (file)
@@ -67,7 +67,7 @@ public slots:
   void onModifyProcRes(const QString &text);
   void onModifyCompoList(const QString &text);
   void onModifyResourceList(const QString &text);
-
+  void onModifyUsePyCache(int val);
 
 protected:
   bool _advanced;
index ac822579624fbd3aa0614f09671c45d77b3e8448..3129f615469621c5f8d80d1c54e5762fcefad471 100644 (file)
            <widget class="QLineEdit" name="le_workdir"/>
           </item>
           <item row="3" column="0" colspan="3">
+            <widget class="QCheckBox" name="ch_pycache">
+              <property name="text">
+              <string>Use python cache</string>
+              </property>
+            </widget>
+          </item>
+          <item row="4" column="0" colspan="3">
            <widget class="QGroupBox" name="groupBox_2">
             <property name="title">
              <string>Parallel parameters</string>
             </layout>
            </widget>
           </item>
-          <item row="4" column="1">
+          <item row="5" column="1">
            <spacer name="verticalSpacer">
             <property name="orientation">
              <enum>Qt::Vertical</enum>
index e649ecfbb4b2c5ecee06f97620b51eafa9cf7dd4..5a88fb7f9ed84a871a65184e156f44f0193376e8 100644 (file)
@@ -36,7 +36,6 @@ FormContainer::FormContainer(QWidget *parent):FormContainerBase(parent),cb_type(
   FormContainer::FillPanel(0); // --- set widgets before signal connexion to avoid false modif detection
   connect(cb_type, SIGNAL(activated(const QString&)),this, SLOT(onModifyType(const QString&)));
   connect(ch_aoc,SIGNAL(stateChanged(int)),this,SLOT(onModifyAOC(int)));
-  connect(ch_pycache,SIGNAL(stateChanged(int)),this,SLOT(onModifyStorePyCache(int)));
 }
 
 FormContainer::~FormContainer()
@@ -50,7 +49,6 @@ void FormContainer::FillPanel(YACS::ENGINE::Container *container)
   if(container)
   {
     ch_aoc->setCheckState(container->isAttachedOnCloning()?Qt::Checked:Qt::Unchecked);
-    ch_pycache->setCheckState(container->storeContext()?Qt::Checked:Qt::Unchecked);
   }
   cb_type->clear();
   cb_type->addItem("mono");
@@ -96,21 +94,3 @@ void FormContainer::onModifyAOC(int val)
   if(prop!=val2)
     onModified();
 }
-
-void FormContainer::onModifyStorePyCache(int val)
-{
-  if (!_container)
-    return;
-  bool val2(false);
-  if(val==Qt::Unchecked)
-    val2=false;
-  if(val==Qt::Checked)
-    val2=true;
-  bool prop = _container->storeContext();
-  int prop2((int)val2);
-  std::ostringstream oss; oss << prop2;
-  //_properties[YACS::ENGINE::Container::AOC_ENTRY]=oss.str();
-  _container->setStoreContext(val2);
-  if(prop!=val2)
-    onModified();
-}
index 190048f39ce3d9c7475cb4f163c7b584ebc9b2df..d7a601761d15a4afe289c3d369147505c0311a87 100644 (file)
@@ -43,7 +43,6 @@ public:
 public slots:
   void onModifyType(const QString &text);
   void onModifyAOC(int val);
-  void onModifyStorePyCache(int val);
 private:
   QComboBox *cb_type;
 };
index 52a8e539edc60c0c410c424d61433a9e784163bd..010589813abbee16a92b25c9cc5e3cc72b1fb981 100644 (file)
           </property>
          </widget>
         </item>
-        <item>
-         <widget class="QCheckBox" name="ch_pycache">
-          <property name="text">
-           <string>Store python cache</string>
-          </property>
-         </widget>
-        </item>
        </layout>
       </item>
      </layout>
index 33f7fb307bca0285d6fecba6d2b8e1c387ab4f2b..579d49b8bf4ef2aad6fca55ccdfcef56499210d1 100644 (file)
@@ -549,7 +549,7 @@ void PythonNode::executeRemote()
         squeezeMemoryRemote();
   }
   //
-  if(!storeContext())
+  if(!isUsingPythonCache())
   {
     if(!CORBA::is_nil(_pynode))
       {
@@ -744,17 +744,17 @@ bool PythonNode::canAcceptImposedResource()
 
 std::string PythonNode::pythonEntryName()const
 {
-  if(storeContext())
+  if(isUsingPythonCache())
     return "DEFAULT_NAME_FOR_UNIQUE_PYTHON_NODE_ENTRY";
   else
     return getName();
 }
 
-bool PythonNode::storeContext()const
+bool PythonNode::isUsingPythonCache()const
 {
   bool found = false;
   if(_container)
-    found = _container->storeContext();
+    found = _container->isUsingPythonCache();
   return found;
 }
 
index 9db3862b7b304d850db880e56b121690b2235170..12ba7891d2815e7c4a5c32a4f88729c599133e85 100644 (file)
@@ -91,7 +91,7 @@ namespace YACS
       void imposeResource(const std::string& resource_name,
                           const std::string& container_name) override;
       bool canAcceptImposedResource()override;
-      bool storeContext()const;
+      bool isUsingPythonCache()const;
       std::string getContainerLog();
       PythonNode* cloneNode(const std::string& name);
       virtual std::string typeName() { return "YACS__ENGINE__PythonNode"; }
diff --git a/src/yacsloader/samples/wlm_2foreach_with_cache.xml b/src/yacsloader/samples/wlm_2foreach_with_cache.xml
new file mode 100644 (file)
index 0000000..653489c
--- /dev/null
@@ -0,0 +1,203 @@
+<?xml version='1.0' encoding='iso-8859-1' ?>
+<proc name="2foreach_with_cache">
+   <property name="executor" value="workloadmanager"/>
+   <type name="string" kind="string"/>
+   <struct name="Engines/dataref">
+      <member name="ref" type="string"/>
+   </struct>
+   <type name="bool" kind="bool"/>
+   <sequence name="boolvec" content="bool"/>
+   <type name="double" kind="double"/>
+   <sequence name="dblevec" content="double"/>
+   <objref name="file" id="file"/>
+   <type name="int" kind="int"/>
+   <sequence name="intvec" content="int"/>
+   <struct name="stringpair">
+      <member name="name" type="string"/>
+      <member name="value" type="string"/>
+   </struct>
+   <sequence name="propvec" content="stringpair"/>
+   <objref name="pyobj" id="python:obj:1.0"/>
+   <sequence name="seqboolvec" content="boolvec"/>
+   <sequence name="seqdblevec" content="dblevec"/>
+   <sequence name="seqint" content="int"/>
+   <sequence name="seqintvec" content="intvec"/>
+   <sequence name="seqpyobj" content="pyobj"/>
+   <sequence name="stringvec" content="string"/>
+   <sequence name="seqstringvec" content="stringvec"/>
+   <container name="DefaultContainer">
+      <property name="container_kind" value="Salome"/>
+      <property name="attached_on_cloning" value="0"/>
+      <property name="container_name" value="FactoryServer"/>
+      <property name="name" value="localhost"/>
+   </container>
+   <container name="c1">
+      <property name="container_kind" value="Salome"/>
+      <property name="attached_on_cloning" value="0"/>
+      <property name="nb_parallel_procs" value="1"/>
+      <property name="type" value="multi"/>
+      <property name="use_py_cache" value="1"/>
+   </container>
+   <container name="c2">
+      <property name="container_kind" value="Salome"/>
+      <property name="attached_on_cloning" value="0"/>
+      <property name="nb_parallel_procs" value="4"/>
+      <property name="type" value="multi"/>
+      <property name="use_py_cache" value="1"/>
+   </container>
+   <inline name="Begin">
+      <script><code><![CDATA[import time
+vals = [ i for i in range(40)]
+nbbranches = len(vals)
+t0=time.time()
+]]></code></script>
+      <outport name="t0" type="pyobj"/>
+      <outport name="vals" type="intvec"/>
+      <outport name="nbbranches" type="int"/>
+   </inline>
+   <inline name="End">
+      <script><code><![CDATA[import time
+tf=time.time()
+total_time=int(tf-t0)
+
+ok = True
+s_expected = sum(vals)
+
+tr1={}
+for cont_name, s in r1:
+    if cont_name in tr1.keys():
+        v = tr1[cont_name]
+        if s > v:
+            tr1[cont_name] = s
+    else:
+        tr1[cont_name] = s
+
+s1 = sum(tr1.values())
+if s_expected != s1:
+    ok = False
+    print("Error on the first foreach.")
+    print("Expected sum:", s_expected)
+    print("Obtained sum:", s1)
+
+tr2={}
+for cont_name, s in r2:
+    if cont_name in tr2.keys():
+        v = tr2[cont_name]
+        if s > v:
+            tr2[cont_name] = s
+    else:
+        tr2[cont_name] = s
+
+s2 = sum(tr2.values())
+if s_expected != s2:
+    ok = False
+    print("Error on the second foreach.")
+    print("Expected sum:", s_expected)
+    print("Obtained sum:", s2)
+
+#print(r1)
+#print(r2)
+]]></code></script>
+      <load container="DefaultContainer"/>
+      <inport name="t0" type="pyobj"/>
+      <inport name="r1" type="seqpyobj"/>
+      <inport name="r2" type="seqpyobj"/>
+      <inport name="vals" type="intvec"/>
+      <outport name="total_time" type="int"/>
+      <outport name="ok" type="bool"/>
+   </inline>
+   <foreach name="ForEach1" nbranch="1" loopWeight="-1" type="int">
+      <remote name="PyNode1" elementaryWeight="-1">
+         <script><code><![CDATA[import time
+if "s" not in globals():
+    # long initialization here to be done only once
+    time.sleep(1)
+    s=0
+s += v
+container_name = my_container.name
+result = (container_name, s)
+time.sleep(1)
+]]></code></script>
+         <load container="c1"/>
+         <inport name="v" type="int"/>
+         <outport name="result" type="pyobj"/>
+      </remote>
+   </foreach>
+   <foreach name="ForEach2" nbranch="1" loopWeight="-1" type="int">
+      <remote name="PyNode2" elementaryWeight="-1">
+         <script><code><![CDATA[import time
+if "s" not in globals():
+    # long initialization here to be done only once
+    time.sleep(1)
+    s=0
+s += v
+container_name = my_container.name
+result = (container_name, s)
+time.sleep(1)
+]]></code></script>
+         <load container="c2"/>
+         <inport name="v" type="int"/>
+         <outport name="result" type="pyobj"/>
+      </remote>
+   </foreach>
+   <control> <fromnode>Begin</fromnode> <tonode>ForEach1</tonode> </control>
+   <control> <fromnode>Begin</fromnode> <tonode>ForEach2</tonode> </control>
+   <control> <fromnode>Begin</fromnode> <tonode>End</tonode> </control>
+   <control> <fromnode>ForEach1</fromnode> <tonode>End</tonode> </control>
+   <control> <fromnode>ForEach2</fromnode> <tonode>End</tonode> </control>
+   <datalink control="false">
+      <fromnode>Begin</fromnode> <fromport>t0</fromport>
+      <tonode>End</tonode> <toport>t0</toport>
+   </datalink>
+   <datalink control="false">
+      <fromnode>Begin</fromnode> <fromport>vals</fromport>
+      <tonode>End</tonode> <toport>vals</toport>
+   </datalink>
+   <datalink control="false">
+      <fromnode>Begin</fromnode> <fromport>vals</fromport>
+      <tonode>ForEach1</tonode> <toport>SmplsCollection</toport>
+   </datalink>
+   <datalink control="false">
+      <fromnode>Begin</fromnode> <fromport>vals</fromport>
+      <tonode>ForEach2</tonode> <toport>SmplsCollection</toport>
+   </datalink>
+   <datalink control="false">
+      <fromnode>Begin</fromnode> <fromport>nbbranches</fromport>
+      <tonode>ForEach2</tonode> <toport>nbBranches</toport>
+   </datalink>
+   <datalink control="false">
+      <fromnode>Begin</fromnode> <fromport>nbbranches</fromport>
+      <tonode>ForEach1</tonode> <toport>nbBranches</toport>
+   </datalink>
+   <datalink control="false">
+      <fromnode>ForEach1</fromnode> <fromport>evalSamples</fromport>
+      <tonode>ForEach1.PyNode1</tonode> <toport>v</toport>
+   </datalink>
+   <datalink control="false">
+      <fromnode>ForEach2</fromnode> <fromport>evalSamples</fromport>
+      <tonode>ForEach2.PyNode2</tonode> <toport>v</toport>
+   </datalink>
+   <datalink control="false">
+      <fromnode>ForEach1.PyNode1</fromnode> <fromport>result</fromport>
+      <tonode>End</tonode> <toport>r1</toport>
+   </datalink>
+   <datalink control="false">
+      <fromnode>ForEach2.PyNode2</fromnode> <fromport>result</fromport>
+      <tonode>End</tonode> <toport>r2</toport>
+   </datalink>
+   <parameter>
+      <tonode>ForEach1</tonode><toport>nbBranches</toport>
+      <value><int>1</int></value>
+   </parameter>
+   <parameter>
+      <tonode>ForEach2</tonode><toport>nbBranches</toport>
+      <value><int>1</int></value>
+   </parameter>
+   <presentation name="Begin" x="9" y="86" width="158" height="117" expanded="1" expx="9" expy="86" expWidth="158" expHeight="117" shownState="0"/>
+   <presentation name="End" x="402.5" y="85" width="158" height="144" expanded="1" expx="402.5" expy="85" expWidth="158" expHeight="144" shownState="0"/>
+   <presentation name="ForEach1.PyNode1" x="9.5" y="88" width="158" height="63" expanded="1" expx="9.5" expy="88" expWidth="158" expHeight="63" shownState="0"/>
+   <presentation name="ForEach2.PyNode2" x="13" y="92" width="158" height="63" expanded="1" expx="13" expy="92" expWidth="158" expHeight="63" shownState="0"/>
+   <presentation name="ForEach1" x="201.5" y="146" width="171.5" height="155" expanded="1" expx="201.5" expy="146" expWidth="171.5" expHeight="155" shownState="0"/>
+   <presentation name="ForEach2" x="204" y="313.5" width="175" height="159" expanded="1" expx="204" expy="313.5" expWidth="175" expHeight="159" shownState="0"/>
+   <presentation name="__ROOT__" x="0" y="0" width="564.5" height="476.5" expanded="1" expx="0" expy="0" expWidth="564.5" expHeight="476.5" shownState="0"/>
+</proc>
index 5c3c745c0d26fd73cf321ef14b91a61f7223a98e..5b014bffcba1d07c691985f88d344049b577aec1 100755 (executable)
@@ -28,8 +28,8 @@ sleep 3
 export TESTCOMPONENT_ROOT_DIR=`pwd`/../runtime
 
 #python3 -m unittest discover
-MODULES_TO_TEST=testEdit testExec testFEDyn testFEDyn2 testLoader testProgress \
-testRefcount testResume testSave testSaveLoadRun  testValidationChecks
+MODULES_TO_TEST="testEdit testExec testLoader testProgress testRefcount \
+testResume testSave testSaveLoadRun testValidationChecks"
 
 python3 -m unittest $MODULES_TO_TEST
 ret=$?
index 0dd3f817c2ca698f83ee0caace05049bbdc6e0c5..e40d0c4e49c76962b3ed0100a8c40e4033535009 100755 (executable)
@@ -68,7 +68,7 @@ class TestEdit(unittest.TestCase):
       # if no property is set, the old executor is used
       proc.setProperty("executor", "workloadmanager")
       # reuse the same python context for every execution
-      cont.setStoreContext(True)
+      cont.usePythonCache(True)
       # save & reload
       schema_file = os.path.join(dir_test,"pynode_with_cache1.xml")
       proc.saveSchema(schema_file)
@@ -107,7 +107,7 @@ class TestEdit(unittest.TestCase):
       proc.edAddChild(n2)
       proc.edAddCFLink(n1,n2)
       # reuse the same python context for every execution
-      cont.setStoreContext(True)
+      cont.usePythonCache(True)
       # save & reload
       schema_file = os.path.join(dir_test,"pynode_with_cache2.xml")
       proc.saveSchema(schema_file)
index 6b522e74179ce3926f81d4c0b1fc707cfc1519aa..8377ccf4280dee7375e5f854ec1ff7a915881aab 100755 (executable)
@@ -53,7 +53,24 @@ class TestEdit(unittest.TestCase):
         # lower time means some resources are overloaded
         self.assertTrue(execution_time > 13)
         # The containers need some time to be launched.
-        # We need some room for that.
+        # We need some delay to add to the 15s.
+        self.assertTrue(execution_time < 20)
+
+    def test2(self):
+        """ Two parallel foreach-s with different containers and python nodes
+            using cache.
+        """
+        proc = self.l.load("samples/wlm_2foreach_with_cache.xml")
+        self.e.RunW(proc,0)
+        ok = proc.getChildByName("End").getOutputPort("ok")
+        self.assertTrue(ok)
+        total_time = proc.getChildByName("End").getOutputPort("total_time")
+        # theoretical time should be 16s
+        execution_time = total_time.getPyObj()
+        # lower time means some resources are overloaded
+        self.assertTrue(execution_time > 14)
+        # The containers need some time to be launched.
+        # We need some delay to add to the 15s.
         self.assertTrue(execution_time < 20)
 
 if __name__ == '__main__':