Как я могу реализовать сопрограммы для параллельной задачи - PullRequest
0 голосов
/ 08 мая 2018

Итак, у меня есть этот кусок кода :

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
        }
}

Это занимает более 4 м на JVM. оригинальный образец в cpp использует 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 в массив массивов и join() в конце, но безуспешно ..

Можно ли использовать сопрограмму для параллельной задачи, подобной этой? Если да, что я делаю не так?

1 Ответ

0 голосов
/ 08 мая 2018

Вместо сопрограмм вы должны рассмотреть встроенный в 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)
        }
...