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,这可能会改变。
我在 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,这可能会改变。