2017-05-04 45 views
0

下面的代碼可以並行化嗎?我看着Cyton的prange,但無法弄清楚它是如何工作的。 prange是否將不同內核上的內部環路並行化?對於下面的代碼,我該如何並行化它?使用cython並行化

@cython.boundscheck(False) 
def gs_iterate_once(double[:,:] doc_topic, 
        double[:,:] topic_word, 
        double[:] topic_distribution, 
        double[:] topic_probabilities, 
        unsigned int[:,:] doc_word_topic, 
        int num_topics): 
    cdef unsigned int doc_id 
    cdef unsigned int word_id 
    cdef unsigned int topic_id 
    cdef unsigned int new_topic 
    for i in xrange(doc_word_topic.shape[0]): 
    doc_id = doc_word_topic[i, 0] 
    word_id = doc_word_topic[i, 1] 
    topic_id = doc_word_topic[i, 2] 

    doc_topic[doc_id, topic_id] -= 1 
    topic_word[topic_id, word_id] -= 1 
    topic_distribution[topic_id] -= 1 

    for j in xrange(num_topics): 
     topic_probabilities[j] = (doc_topic[doc_id, j] * topic_word[j, word_id])/topic_distribution[j] 

    new_topic = draw_topic(np.asarray(topic_probabilities)) 

    doc_topic[doc_id, new_topic] += 1 
    topic_word[new_topic, word_id] += 1 
    topic_distribution[new_topic] += 1 
    # Set the new topic 
    doc_word_topic[i, 2] = new_topic 

回答

2

prange使用OpenMP的確是shared-memory parallelism。因此,在單臺計算機上,它將創建可在不同內核上運行的線程,並訪問相同的內存池。

對於您演示的例程,第一步是瞭解哪些部分可以並行化。通常,使用作爲第一索引i的數據,僅在元件i上操作而不是例如i-1i+1,使得問題可並行化。這不是這種情況,所以你需要找到一種方法使計算更加獨立。

真正找到特定的並行模式超出了SO回答,但我會提一些建議:

  1. 什麼是的PRANGE必須全部cythonized。 Python調用在一個線程中是不可能的。 + @DavidW的建議:當with gil塊的一部分時,Python調用是可能的。
  2. 這裏的一個典型建議是檢查一旦你的代碼已經獨立於循環排序,當從n-1到0而不是從0到n-1運行索引時,結果是相同的
  3. 一些評論和說明性的例子:https://homes.cs.washington.edu/~jmschr/lectures/Parallel_Processing_in_Python.htmlCython prange slower for 4 threads then with rangehttp://nealhughes.net/parallelcomp2/http://www.perrygeo.com/parallelizing-numpy-array-loops-with-cython-and-mpi.html
+0

回覆點1 - 我可以建議一個補充:如果你把它們放在一個'gil:'塊中,允許Python調用。只要這是循環的一小部分,那麼性能成本並不算太差。 – DavidW

2

@ PierredeBuyl的回答給出了什麼prange做和如何使用它的一個很好的輪廓。

這是更涉及代碼的一些具體意見:

  • 您不能並行外環:

    doc_topic[doc_id, topic_id] -= 1 
    

    和其他變量和+=1類似的。這些修改了所有循環之間共享的變量,並且會導致不一致的結果。

  • 如果您要並行化外部循環,則topic_probabilities[j] = ...會出現類似問題。

  • 你可以很容易地並行內部循環for j in xrange(num_topics): - 這隻會修改依賴於索引'j'的東西,所以不存在爭取修改相同數據的線程問題。 (但是,每次啓動一個多線程的區域時的性能爲代價的,所以通常嘗試並行外環來避免這一點 - 這取決於數組的大小,你可能沒有太大的收穫)