2013-11-24 137 views
0

我已經寫了下面的Scala代碼來計算距離矩陣:斯卡拉嵌套for循環在流

def dist(fasta: Stream[FastaRecord], f: (FastaRecord, FastaRecord) => Int) = { 
    val inF = fasta.par 
    for (i <- inF; j <- inF) 
    yield (f(i, j)) 
} 

這段代碼在這個意義上,我得到極好的並行的偉大工程。不幸的是,由於f(i,j)與f(j,i)相同,我所做的工作是我需要的兩倍。我想要做的是在流中的i + 1處啓動j。我可以用指數做到這一點:

for (i <- 0 until inF.length - 1; j <- i+1 until inF.length) 
    yield(f(inF(i), inF(j))) 

然而,要求inF.length我聽說是不是在流好,這不給我的並行性。

我認爲應該有一種方法來做這個迭代,但是,我還沒有拿出任何東西。

謝謝!吉姆

+0

流緩存他們的結果,就像[斐波那契計算的例子](http://www.derekwyatt.org/2011/07/29/understanding-scala-streams-through-fibonacci/)。所以在第一次「j」遍歷整個流之後,它應該像普通列表一樣快。這意味着我認爲你最好在開始時用「長度」來評估你的流,然後用「f」函數只執行一半的並行計算。我對此進行評論,以便您瞭解Streams __after__的性能,它們已經迭代過一次。 –

+1

我認爲這裏更大的問題是Streams沒有針對隨機訪問進行優化,所以'inF(i)'和'inF(j)'操作將會很慢。 – DaoWen

回答

1

我想用zipWithIndex可能會得到你,你找什麼:

def dist(fasta: Stream[FastaRecord], f: (FastaRecord, FastaRecord) => Int) = { 
    val inF = fasta.zipWithIndex.par 
    for ((x, i) <- inF; (y, j) <- inF; if i <= j) 
    yield f(x, y) 
} 

通過過濾i <= j可以消除重複(鏡像)的情況。但是,我得到一個警告,當我編譯如下:

warning: `withFilter' method does not yet exist on scala.collection.parallel.immutable.ParSeq[(FastaRecord, Int)], using `filter' method instead 

我不認爲這真的是一個問題,但我也不知道如何剿錯誤...