Groovy 与串行相比,Gpars 并行性能较差

Groovy Gpars poor parallel performance compared to serial

我在 i7-2960xm(4 核超线程)上试验多线程时,Groovy Gpars 的性能低于预期。在我的测试中,我一直在使用递归 fib 计算器来模拟工作量:

def fibRecursive(int index) {
    if (index == 0 || index == 1) {
        return index
    }
    else {
        return fibRecursive(index - 2) + fibRecursive(index - 1)
    }
}

为了测试 Gpars,我目前使用以下代码:

def nums = [36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36]

GParsPool.withPool(4) {
    nums.eachParallel {
        SplitTimer internalTimer = new SplitTimer()
        println("fibRecursive(${it}): ${fibRecursive(it)}")
        internalTimer.split("fibRecursive(${it})")

        for (instance in internalTimer.splitTimes) {
            println(instance)
        }
    }
}

withPool(4) 并行计算 fib(36) 大约需要 1.9 秒。 withPool(1) 大约需要 1.4 秒,我认为这与在 Gpars 外部调用函数有些相似,但只需要 0.4 秒,例如:

nums.each {
    SplitTimer internalTimer = new SplitTimer()
    println("fibRecursive(${it}): ${fibRecursive(it)}")
    internalTimer.split("fibRecursive(${it})")

    for (instance in internalTimer.splitTimes) {
        println(instance)
    }
}

有人可以解释为什么我会遇到这种性能下降吗?谢谢!

这是我的 SplitTimer 以防万一:

class SplitTimer {
    long initialTime
    int instances = 0

    class Instance {
        int index
        String name
        long time

        def elapsed() {
            return time - initialTime
        }

        def Instance(String instanceName) {
            this.index = this.instances++
            this.name = instanceName
            this.time = System.nanoTime()
        }

        String toString() {
            return "[Instance ${this.index}: \"${this.name}\" (${Formatter.elapsed(this.elapsed())} elapsed)]"
        }
    }

    def splitTimes = []

    def SplitTimer() {
        def initialInstance = new Instance("Start")
        this.initialTime = initialInstance.time
        splitTimes.add(initialInstance)
    }

    def split(String instanceName) {
        splitTimes.add(new Instance(instanceName))
    }
}

class Formatter {
    static int hours
    static int minutes
    static int seconds
    static int nanoseconds

    static setValues(time) {
        nanoseconds = time % 10**9

        seconds = time / 10**9
        minutes = seconds / 60
        hours = minutes / 60

        seconds %= 60
        minutes %= 60
    }

    static elapsed(time) {
        setValues(time)
        return "${hours}:" + "${minutes}:".padLeft(3, "0") + "${seconds}.".padLeft(3, "0") + "${nanoseconds}".padLeft(9,"0")
    }

    static absolute(time) {
        setValues(time)
        hours %= 24
        return "${hours}:".padLeft(3, "0") + "${minutes}:".padLeft(3, "0") + "${seconds}.".padLeft(3, "0") + "${nanoseconds}".padLeft(9,"0")
    }
}

并行化少量函数调用所需的工作量可能比按顺序 运行 它们所需的工作量更多。但是,如果您使用非常大的数字调用 fibonacci,这可能会改变。