考虑C ++类。第一个是分支类:
class Branch{
map<string,double> properties;
}
即。 分支对象仅由其属性表征,这些属性存储在地图中。每个属性都有一个名称,并与double值相关联。第二个是树类,由许多分支组成:
class Tree{
vector<*Branch> tree;
void addBranch(int index); //adds a branch to tree vector at index
void removeBranch(int index); //removes branch at index and and its descendents
double getProperty(int index, string name);//gets value of property name of branch at index
void addProperty(int index, string name, double value);
void setProperty(int index, string name, double value);
}
现在假设使用cython包装树类。然后,在Python中,我们可以操作PyTree对象,添加和删除分支并操纵每个分支的属性。考虑以下python程序:
tree=PyTree()
for i in range(TotalTime):
k=random.random()
if k>0.1:
tree.addBranch(random_index) #it is not important how we get the index
tree.addProperty(random_index,'prop1',1)
tree.addProperty(random_index,'prop2',1)
k=random.random()
if k>0.9:
tree.removeBranch(random_index)
for j in range(NumberOfBranches): #it's not important how we get the number of branches
operation1(j,'prop1') # assume this functions were defined
operation2(j,'prop2')
在这个程序中,我随机添加和删除分支。每个分支都有两个属性 prop1 和 prop2 。有一个 operation1 函数在&#39; prop1&#39; <上执行涉及 getProperty 和 setProperty 函数的操作/ em>和 operation2 函数在&#39; prop2&#39; 上执行相同的操作。
我想要的是让一个处理器(或线程)执行每个操作。由于程序不断调用外部C ++库,我应该使用线程而不是多处理器吗?
我应该如何实现并行化?我尝试用https://www.quantstart.com/articles/parallelising-python-with-threading-and-multiprocessing鼓励自己,但是当我同时使用线程或多处理器时,我会得到一个较慢的程序......
答案 0 :(得分:1)
我建议使用threading
- 因为主要的工作是在你的包装C ++函数中完成的,那么你应该能够释放GIL并让所有东西可靠地并行工作。
一个好的一般规则是尽可能少地创建新线程(这可能是一个有点慢的操作),然后将它们提供给它们,直到完成为止。你在评论中说你根本不关心执行操作的顺序(好!)。考虑到这一点,我将建议感觉包含操作的lambda函数到Queue
并让线程选择它们并运行时间:
然后,以下代码进入for i in range(TotalTime):
循环,取代for j in range(NumberOfBranches):
:
q = Queue()
def thread_func():
"""A function for each thread to run.
It waits to get an item off the queue and then runs that item.
None is used to indicate that we're done. If we get None, we
put it pack on the Queue to ensure every thread terminates"""
while True:
f = q.get()
if f is None:
q.put(None)
return
f()
# make and start the threads.
# "no_threads" should be something similar to the number of cores you have.
# 4-8 might be a good number to try?
threads = [ threading.Thread(target=thread_func) for n in range(no_threads) ]
[ t.start() for t in threads ]
# put the required operations on the Queue
for j in (NumberOfBranches):
# note the awkward syntax to
# ensure we capture j: http://stackoverflow.com/a/7514158/4657412
q.put(lambda j=j: operation1(x,"prop1"))
q.put(lambda j=j: operation2(x,"prop2"))
q.put(None) # to terminate
# wait for threads to finish
[ t.join() for t in threads ]
为了让线程实际并行工作,你需要确保在你的Cython包装器中释放GIL:
def operation1(a,b):
with nogil:
cplusplus_operation1(a,b)
我对使用multiprocessing
operation1/2
修改了C ++数据,那么您可能会发现修改后的数据不会在整个过程中共享而不需要您做出特别的努力(这会使操作失败!)