gpt4 book ai didi

scala - Scala 如何在这里使用我的所有内核?

转载 作者:行者123 更新时间:2023-12-04 15:18:33 26 4
gpt4 key购买 nike

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功能。

它有效……计算结果很棒!

然而我去实现了另一个版本, reduceResPar ,在前几个分支使用 fork-join 来并行化计算。但它没有加快速度。

然后我回去意识到..上面的版本, reduceRes ,已经在我的机器上使用了所有 12 个内核!!它怎么能做到这一点?我以为只有1个核心!

此代码来自 Coursera 上的 Parallel Programming 类(class),在第 2 周的最后一课中,我们正在学习并行前缀扫描操作。

最佳答案

How can it do that? I thought it would just be 1 core!



您看到所有内核都在使用的事实并不意味着您的代码执行是并行的。我们可以从实现中看到它是顺序的,但是我们不知道我们的单个线程将在每个周期被操作系统调度到哪个 CPU 上。

当您在线程内执行一个方法时,操作系统会根据它管理的优先级队列决定它将获得多少 CPU 时间片以及何时获得。

要查看您的算法可能在不同的内核上运行,我们可以询问操作系统当前正在哪个逻辑内核上执行我们的线程。我为 Windows 准备了一个小实现,它有一个名为 GetCurrentProcessorNumber() 的本地 WinAPI 方法。它返回我们正在执行的处理器编号。我们将使用 JNA例如:

构建.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)
}

现在让我们创建一棵树并执行:
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 个逻辑核心的计算机):

第一的:
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

第二:
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

在每次执行期间,您会看到正在执行的线程在 3 个不同的内核(0、1 和 3)上获得了执行切片,而我们仍在单线程环境中运行。这表明,尽管您的算法的计算绝对是顺序的,但这并不意味着您不会看到所有内核都在运行。

关于scala - Scala 如何在这里使用我的所有内核?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45611701/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com