加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

Scala如何在这里使用我的所有核心?

发布时间:2020-12-16 18:51:17 所属栏目:安全 来源:网络整理
导读: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
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个内核!它怎么能这样做?我以为它只是一个核心!

这段代码来自Coursera的并行编程课程.在第2周的最后一堂课中,我们学习了并行前缀扫描操作.

解决方法

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

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

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

要查看您的算法可能在不同的内核上运行,我们可以询问操作系统当前正在执行我们的线程的逻辑内核.我已经为Windows准备了一个小实现,它有一个名为GetCurrentProcessorNumber()的本机WinAPI方法,它返回我们正在执行的处理器号.我们将使用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,f))
    NodeRes(tL,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上执行了一条执行,而我们仍然在单线程环境中运行.这表明虽然算法的计算肯定是连续的,但这并不意味着你不会看到你所有的核心.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读