2017-08-10 7 views
6
object PrefixScan { 
    sealed abstract class Tree[A] 
    case class Leaf[A](a: A) extends Tree[A] 
    case class Node[A](l: Tree[A], r: Tree[A]) extends Tree[A] 

    sealed abstract class TreeRes[A] { val res : A } 
    case class LeafRes[A](override val res: A) extends TreeRes[A] 
    case class NodeRes[A](l : TreeRes[A], override val res: A, r: TreeRes[A]) extends TreeRes[A] 

    def reduceRes[A](t: Tree[A], f:(A,A)=>A): TreeRes[A] = t match { 
    case Leaf(v) => LeafRes(v) 
    case Node(l, r) => { 
     val (tL, tR) = (reduceRes(l, f), reduceRes(r, f)) 
     NodeRes(tL, f(tL.res, tR.res), tR) 
    } 
    } 
} 

私はreduceRes機能について懸念しています。Scalaはここですべてのコアをどのように使用しますか?

これは機能します...計算結果は素晴らしいです!

しかし、別のバージョンのreduceResParを実装しましたが、最初の数個の分岐でfork-joinを使用して計算を並列化しました。しかし、スピードアップはありませんでした。

私は戻ってきました。上記のバージョンreduceResは、すでに12個のコアをすべてマシンで使用しています。それはどうすればできますか?私はそれがちょうど1つのコアだろうと思った!

このコードはCourseraの並列プログラミングコースからのものです。第2週の最後の講義では、並列プリフィックススキャン操作について学習しています。

+0

2つ以上のコアを使用していますか?このソースの並行性のための機会はないようです。並列コレクションはなく、先物はありません。 – Suma

+0

ツリーインスタンスを作成し、 'reduceRes'をどのように実行するのか、もっと完全な例を投稿できますか? – Suma

+0

私はこのコードでkatieと同じ問題を抱えています:https://pastebin.com/dNFMxN7F concurencyのための機会はありませんが、すべてのコアが使用されています – rubiktubik

答えて

4

どうすればできますか?私はそれがちょうど1つのコアだろうと思った!

すべてのコアが使用されているということは、コードの実行が並行しているわけではありません。実装から順番に見ることができますが、各サイクルでOSによってどの単一CPUがどのCPUをスケジュールするかはわかりません。

スレッド内でメソッドを実行すると、OSは、そのスレッドが管理する優先度キューに従って、どのくらいのCP​​Uタイムスライスを取得するかを決定します。

あなたのアルゴリズムが異なるコアで動作することを確認するには、現在スレッドを実行している論理コアのOSをOSに尋ねることができます。私は、実行中のプロセッサ番号を返すGetCurrentProcessorNumber()というネイティブWinAPIメソッドを持つWindows用の小さな実装を用意しました。私たちは、例えばJNAを使用します:

build.sbt:

"net.java.dev.jna" % "jna" % "4.4.0" 

Java実装:

import com.sun.jna.Library; 
import com.sun.jna.Native; 

public class ProcessorNumberNative { 

    public interface CLibrary extends Library { 
     CLibrary INSTANCE = (CLibrary) 
       Native.loadLibrary("Kernel32.dll", 
         CLibrary.class); 

     Integer GetCurrentProcessorNumber(); 
    } 
} 

今度は、あなたの再帰の各ステップにprintlnを追加してみましょう。

def reduceRes[A](t: Tree[A], f: (A, A) => A): TreeRes[A] = t match { 
    case Leaf(v) => 
    println(s"Logical Processor Number: ${ProcessorNumberNative.CLibrary.INSTANCE.GetCurrentProcessorNumber()}") 
    LeafRes(v) 

    case Node(l, r) => 
    println(s"Logical Processor Number: ${ProcessorNumberNative.CLibrary.INSTANCE.GetCurrentProcessorNumber()}") 
    val (tL, tR) = (reduceRes(l, f), reduceRes(r, f)) 
    NodeRes(tL, f(tL.res, tR.res), tR) 
} 

ここでツリーを作成して実行します。それぞれの間に

Logical Processor Number: 1 
Logical Processor Number: 3 
Logical Processor Number: 1 
Logical Processor Number: 1 
Logical Processor Number: 1 
Logical Processor Number: 1 
Logical Processor Number: 1 
Logical Processor Number: 1 
Logical Processor Number: 3 
Logical Processor Number: 3 
Logical Processor Number: 3 
Logical Processor Number: 3 
Logical Processor Number: 3 

:まず

:セカンド

Logical Processor Number: 1 
Logical Processor Number: 3 
Logical Processor Number: 3 
Logical Processor Number: 3 
Logical Processor Number: 0 
Logical Processor Number: 0 
Logical Processor Number: 0 
Logical Processor Number: 3 
Logical Processor Number: 0 
Logical Processor Number: 0 
Logical Processor Number: 0 
Logical Processor Number: 0 
Logical Processor Number: 0 
def main(args: Array[String]): Unit = { 

    val tree = Node(Leaf(1), 
       Node(Leaf(2), 
        Node(Node(Leaf(24), Leaf(30)), 
          Node(Leaf(3), Node(Leaf(10), Leaf(52)))))) 

    reduceRes(tree, (a: Int, b: Int) => a + b) 
} 

と(私は4つの論理コアを持つコンピュータを実行している)、この二つの異なるランを与えます実行すると、実行中のスレッドは3つの異なるコア0,1,3で実行スライスを取得していますが、1つのスレッドenで実行中ですvironment。これは、あなたのアルゴリズムの計算が間違いなくシーケンシャルであるにもかかわらず、あなたがすべてのコアを見ているわけではないということを示しています。

関連する問題