Ok thank you for this precise answer. 

So to sum up, if I understand correctly: 


    1. I only have to call getSecondOrderIndices() and everything is computed. 
The for loop only access the computed values. 
    2. setBlockSize() defines the number of chunked elements. It linked to the 
number of processes. In the current case, without wrapper and no TBB, this 
means that the computation is performed on one chunk after another. And if the 
wrapper allows multiprocessing, several chunks are computed at the same time. 

Pamphile ROY 


De: "regis lebrun" <[email protected]> 
À: "Pamphile ROY" <[email protected]> 
Cc: "users" <[email protected]> 
Envoyé: Samedi 22 Octobre 2016 15:16:09 
Objet: Re: [ot-users] Pickling and parallelism 

Hi Pamphile, 

First of all, the SensitivityAnalysis class allows you to compute first and 
second order Sobol indices, in addition to the first order total indices. These 
indices are computed thanks to the computeSobolIndices() method, which is 
protected so is not exposed into the Python interface. 
The behaviour of the class is the following: 
+ At the first call to either getFirstOrderIndices() or getTotalOrderIndices(), 
if no previous call to getSecondOrderIndices() has been made, a call to the 
computeSobolIndices() method is done and both the first order and total order 
indices are computed. THIS COMPUTATION IS DONE FOR ALL THE OUTPUTS IN ONE RUN. 
+ At a second call to either getFirstOrderIndices() or getTotalOrderIndices(), 
no new computation is done, you get a value already computed and stored into 
the relevant data structure 
+ At the first call to getSecondOrderIndices(), all the indices (first order, 
total order and second order) are computed. THIS COMPUTATION IS DONE FOR ALL 
THE OUTPUTS IN ONE RUN. 
+ At a second call to either getFirstOrderIndices(), getTotalOrderIndices() or 
getSecondOrderIndices(), no new computation is done. 

The good practice is then to first call getSecondOrderIndices() if you need 
both first and second order indices, otherwise the first order indices will be 
computed twice. 

Concerning the loop over the outputs, you will not get any acceleration if you 
parallelize the loop as the FIRST call to any of the getXXXIndices(int) will 
start the computation of ALL the indices for ALL the outputs. The key point is 
thus to efficiently compute all these indices, which is done by providing an 
efficient implementation of the _exec_sample() method in your wrapper. 

I checked the source code of SensitivityAnalysis::computeSobolIndices() in 
OT1.6, and the conclusion is: 

+ there is no use of TBBs here 
+ the model you provide to the constructor is called over samples (hence the 
interest in providing an _exec_sample method into your wrapper) 
+ the model is called over the two samples you provide to the constructor, each 
call is N evaluations 
+ the model *should be* called over samples of much larger size if all the 
scramble inputs were pre-computed, which could exhaust the available memory. To 
avoid this, the evaluation over the scrambled inputs are partitioned into 
chunks of size blockSize (excepted the last chunk which can have a smaller size 
as it contains the remaining computations), which is precisely what you tune 
thanks to the setBlockSize() method. 

In your case, depending on the amount of memory you have and the distribution 
scheduler you use, you should set the block size to the largest possible value 
and call getSecondOrderIndices() first (the argument can be any valid index 
value) if you need second order indices, as it will compute all the indices at 
once, instead of calling first getFirstOrderIndices() then 
getSecondOrderIndices() as it would compute the first order and total order 
indices twice. 

The technology you use to implement _exec_sample is your choice, but here 
otwrapy could help. 

The key point is that you don't need to parallelize the loop over the output 
dimension, but the evaluation of your model over a sample. 

Cheers 

Régis LEBRUN 

----- Mail original ----- 


De : Pamphile ROY <[email protected]> 
À : regis lebrun <[email protected]> 
Cc : users <[email protected]> 
Envoyé le : Samedi 22 octobre 2016 13h26 
Objet : Re: [ot-users] Pickling and parallelism 

Hi Régis, 

Thanks for your fast reply. 

>From what I understand, otwrapy would do the same thing as 
sobol.setBlockSize(int(ot.ResourceMap.Get("parallel-threads"))). 
So your suggesting to do instead: 
import otwrapy as otw 
model = otw.Parallelizer(ot.PythonFunction(2, 400, func), n_cpus=10) 
If so, what is the benefit of doing it? 

This will only be useful when doing sobol.getFirstOrderIndices(0). 

What I am trying to do is to perform several analysis as I have a functional 
output: 

model = ot.PythonFunction(2, 400, func) 
sobol = ot.SensitivityAnalysis(sample1, sample2, model) 
sobol.setBlockSize(int(ot.ResourceMap.Get("parallel-threads"))) 
indices = [[], [], []] 
for i in range(400): 
indices[1].append(np.array(sobol.getFirstOrderIndices(i))) 
indices[2].append(np.array(sobol.getTotalOrderIndices(i))) 

This work but I want the for loop to be parallel so I tried: 

from pathos.multiprocessing import ProcessingPool, cpu_count 

model = ot.PythonFunction(2, 400, func) 
sobol = ot.SensitivityAnalysis(sample1, sample2, sobol_model) 
sobol.setBlockSize(int(ot.ResourceMap.Get("parallel-threads"))) 

def map_indices(i): 
first = np.array(sobol.getFirstOrderIndices(i)) 
total = np.array(sobol.getTotalOrderIndices(i)) 
return first, total 

pool = ProcessingPool(cpu_count()) 
results = pool.imap(map_indices, range(400)) 
first = np.empty(400) 
total = np.empty(400) 

for i in range(400): 
first[i], total[i] = results.next() 

But in order for this to work, the map_indice function has to be pickled (here 
it uses dill that can serialize close to everything). 
Hence the error I get. 


Thanks again, 

Pamphile ROY 



----- Mail original ----- 
De: "regis lebrun" <[email protected]> 
À: "Pamphile ROY" <[email protected]>, "users" 
<[email protected]> 
Envoyé: Samedi 22 Octobre 2016 12:48:29 
Objet: Re: [ot-users] Pickling and parallelism 

Hi, 

I understand that you have a model that has been interfaced with OpenTURNS 
using 
the OpenTURNSPythonFunction class and you want to perform sensitivity analysis 
using the SensitivityAnalysis class, and you would like to benefit from some 
parallelism in the execution of the analysis. 

The correct way to do that is to provide the _exec_sample method. In this 
method, you are free to use any multithreading/multiprocessing capability you 
want. You may consider either otwrapy (http://felipeam86.github.io/otwrapy/) or 
one of the solutions proposed here: 

http://openturns.github.io/developer_guide/wrapper_development.html or your 
favorite tool. Then, you will get rid of the GIL. 

I cannot help for the second point, as it is far beyond my knowledge on python 
and serialization. 

Cheers 

Régis LEBRUN 


BQ_BEGIN
________________________________ 
De : Pamphile ROY <[email protected]> 
À : [email protected] 
Envoyé le : Vendredi 21 octobre 2016 21h56 
Objet : [ot-users] Pickling and parallelism 



Hi, 


I would have 2 questions: 


1. I have seen that the class (and others) allows some multithreading. From 



my understanding, it is based on TBB and only multithreads the tasks. 

BQ_BEGIN
Thus it is concerned by the GIL. Is there an automatic set up like for 
BQ_END


multithreading but for multiprocessing instead? Any advice? 

BQ_BEGIN


2. Using pathos for multiprocessing, I am trying to dump an instance of 
BQ_END


SensitivityAnalysis but I cannot get it to work even with dill. 

BQ_BEGIN
For information, I am running under macOS sierra and this is OT 1.6 (maybe 
BQ_END


it is coming from here... I am going to upgrade but it means a refactoring on 
my 
side). 

BQ_BEGIN
Here is the following traceback: 


sobol = ot.SensitivityAnalysis(sample1, sample2, sobol_model) 
_f = dill.dumps(sobol) 

File 
BQ_END


"/Users/Pamphile/.virtualenvs/jpod/lib/python2.7/site-packages/dill/dill.py", 
line 243, in dumps 

BQ_BEGIN
dump(obj, file, protocol, byref, fmode, recurse)#, strictio) 
File 
BQ_END


"/Users/Pamphile/.virtualenvs/jpod/lib/python2.7/site-packages/dill/dill.py", 
line 236, in dump 

BQ_BEGIN
pik.dump(obj) 
File 
BQ_END


"/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py",
 
line 224, in dump 

BQ_BEGIN
self.save(obj) 
File 
BQ_END


"/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py",
 
line 306, in save 

BQ_BEGIN
rv = reduce(self.proto) 
File 
BQ_END


"/Applications/OpenTURNS/openturns/lib/python2.7/site-packages/openturns/common.py",
 
line 258, in Object___getstate__ 

BQ_BEGIN
study.add('instance', self) 
File 
BQ_END


"/Applications/OpenTURNS/openturns/lib/python2.7/site-packages/openturns/common.py",
 
line 688, in add 

BQ_BEGIN
return _common.Study_add(self, *args) 
NotImplementedError: Wrong number or type of arguments for overloaded 
BQ_END


function 'Study_add'. 

BQ_BEGIN
Possible C/C++ prototypes are: 
OT::Study::add(OT::InterfaceObject const &) 
OT::Study::add(OT::String const &,OT::InterfaceObject const 
BQ_END


&,OT::Bool) 

BQ_BEGIN
OT::Study::add(OT::String const &,OT::InterfaceObject const &) 
OT::Study::add(OT::PersistentObject const &) 
OT::Study::add(OT::String const &,OT::PersistentObject const 
BQ_END


&,OT::Bool) 

BQ_BEGIN
OT::Study::add(OT::String const &,OT::PersistentObject const &) 


Thank you for your help! 




Pamphile 
_______________________________________________ 
OpenTURNS users mailing list 
[email protected] 
http://openturns.org/mailman/listinfo/users 



BQ_END





BQ_END

_______________________________________________
OpenTURNS users mailing list
[email protected]
http://openturns.org/mailman/listinfo/users

Reply via email to