如何为并行任务实现协程
How can I implement coroutines for a parallel task
所以,我有 this piece of code:
for (z in 0 until texture.extent.z) {
println(z)
for (y in 0 until texture.extent.y)
for (x in 0 until texture.extent.x) {
val v = Vec3(x, y, z) / texture.extent
var n = when {
FRACTAL -> FractalNoise().noise(v * noiseScale)
else -> 20f * glm.perlin(v)
}
n -= glm.floor(n)
data[x + y * texture.extent.x + z * texture.extent.x * texture.extent.y] = glm.floor(n * 255).b
}
}
在 jvm 上占用超过 4m。 cpp中的original sample使用OpenMp加速计算。
我听说过协程,我希望在这种情况下可以利用它们。
我首先尝试将整个 for
包装到一个 runBlocking
中,因为我确实希望在我继续之前所有协程都已完成。
runBlocking {
for (z in 0 until texture.extent.z) {
println(z)
for (y in 0 until texture.extent.y)
for (x in 0 until texture.extent.x) {
launch {
val v = Vec3(x, y, z) / texture.extent
var n = when {
FRACTAL -> FractalNoise().noise(v * noiseScale)
else -> 20f * glm.perlin(v)
}
n -= glm.floor(n)
data[x + y * texture.extent.x + z * texture.extent.x * texture.extent.y] = glm.floor(n * 255).b
}
}
}
}
但这是抛出不同的线程错误加上最终的 jvm 崩溃
[thread 27624 also had an error][thread 23784 also had an error]# A fatal error has been detected by the Java Runtime Environment:
#
[thread 27624 also had an error][thread 23784 also had an error]# A fatal error has been detected by the Java Runtime Environment:
#
# [thread 14004 also had an error]EXCEPTION_ACCESS_VIOLATION
[thread 32652 also had an error] (0xc0000005)[thread 32616 also had an error]
at pc=0x0000000002d2fd50
, pid=23452[thread 21264 also had an error], tid=0x0000000000007b68
#
# JRE version: Java(TM) SE Runtime Environment (8.0_144-b01) (build 1.8.0_144-b01)
# Java VM: Java HotSpot(TM) 64-Bit Server VM (25.144-b01 mixed mode windows-amd64 compressed oops)
# Problematic frame:
# J 1431 C2 java.util.concurrent.ForkJoinPool$WorkQueue.runTask(Ljava/util/concurrent/ForkJoinTask;)V (86 bytes) @ 0x0000000002d2fd50 [0x0000000002d2f100+0xc50]
#
# Failed to write core dump. Minidumps are not enabled by default on client versions of Windows
#
# An error report file with more information is saved as:
# C:\Users\gBarbieri\IdeaProjects\Vulkan\hs_err_pid23452.log
#
# If you would like to submit a bug report, please visit:
# http://bugreport.java.com/bugreport/crash.jsp
#
Process finished with exit code 1
我也尝试将所有 job
收集到一个 arrayList 中,最后 join()
它们,但没有成功..
协程可以用于像这样的并行任务吗?
如果是,我做错了什么?
您应该考虑 JDK 中内置的并行计算引擎而不是协程:java.util.stream
。你这里有一个令人尴尬的可并行化任务,一个完美的用例。
我会按照这些思路使用一些东西:
IntStream.range(0, extent.x)
.boxed()
.parallel()
.flatMap { x ->
IntStream.range(0, extent.y).boxed().flatMap { y ->
IntStream.range(0, extent.z).mapToObj { z ->
Vec(x, y, z)
}
}
}
.forEach { vec ->
data[vecToArrayIndex(vec)] = computeValue(vec)
}
所以,我有 this piece of code:
for (z in 0 until texture.extent.z) {
println(z)
for (y in 0 until texture.extent.y)
for (x in 0 until texture.extent.x) {
val v = Vec3(x, y, z) / texture.extent
var n = when {
FRACTAL -> FractalNoise().noise(v * noiseScale)
else -> 20f * glm.perlin(v)
}
n -= glm.floor(n)
data[x + y * texture.extent.x + z * texture.extent.x * texture.extent.y] = glm.floor(n * 255).b
}
}
在 jvm 上占用超过 4m。 cpp中的original sample使用OpenMp加速计算。 我听说过协程,我希望在这种情况下可以利用它们。
我首先尝试将整个 for
包装到一个 runBlocking
中,因为我确实希望在我继续之前所有协程都已完成。
runBlocking {
for (z in 0 until texture.extent.z) {
println(z)
for (y in 0 until texture.extent.y)
for (x in 0 until texture.extent.x) {
launch {
val v = Vec3(x, y, z) / texture.extent
var n = when {
FRACTAL -> FractalNoise().noise(v * noiseScale)
else -> 20f * glm.perlin(v)
}
n -= glm.floor(n)
data[x + y * texture.extent.x + z * texture.extent.x * texture.extent.y] = glm.floor(n * 255).b
}
}
}
}
但这是抛出不同的线程错误加上最终的 jvm 崩溃
[thread 27624 also had an error][thread 23784 also had an error]# A fatal error has been detected by the Java Runtime Environment:
#
[thread 27624 also had an error][thread 23784 also had an error]# A fatal error has been detected by the Java Runtime Environment:
#
# [thread 14004 also had an error]EXCEPTION_ACCESS_VIOLATION
[thread 32652 also had an error] (0xc0000005)[thread 32616 also had an error]
at pc=0x0000000002d2fd50
, pid=23452[thread 21264 also had an error], tid=0x0000000000007b68
#
# JRE version: Java(TM) SE Runtime Environment (8.0_144-b01) (build 1.8.0_144-b01)
# Java VM: Java HotSpot(TM) 64-Bit Server VM (25.144-b01 mixed mode windows-amd64 compressed oops)
# Problematic frame:
# J 1431 C2 java.util.concurrent.ForkJoinPool$WorkQueue.runTask(Ljava/util/concurrent/ForkJoinTask;)V (86 bytes) @ 0x0000000002d2fd50 [0x0000000002d2f100+0xc50]
#
# Failed to write core dump. Minidumps are not enabled by default on client versions of Windows
#
# An error report file with more information is saved as:
# C:\Users\gBarbieri\IdeaProjects\Vulkan\hs_err_pid23452.log
#
# If you would like to submit a bug report, please visit:
# http://bugreport.java.com/bugreport/crash.jsp
#
Process finished with exit code 1
我也尝试将所有 job
收集到一个 arrayList 中,最后 join()
它们,但没有成功..
协程可以用于像这样的并行任务吗? 如果是,我做错了什么?
您应该考虑 JDK 中内置的并行计算引擎而不是协程:java.util.stream
。你这里有一个令人尴尬的可并行化任务,一个完美的用例。
我会按照这些思路使用一些东西:
IntStream.range(0, extent.x)
.boxed()
.parallel()
.flatMap { x ->
IntStream.range(0, extent.y).boxed().flatMap { y ->
IntStream.range(0, extent.z).mapToObj { z ->
Vec(x, y, z)
}
}
}
.forEach { vec ->
data[vecToArrayIndex(vec)] = computeValue(vec)
}