[Devoxx FR 2012] – GPGPU facile avec JavaCL, et trivial avec ScalaCL

Dans ce Tools In Action, Olivier Chafik nous a présenté deux de ses projets permettant de faciliter l’utilisation d’OpenCL en Java et en Scala : JavaCL et ScalaCL.

OpenCL est une API en C permettant de faire du calcul distribué en utilisant les cartes graphiques (GPU). Il est le pendant de l’OpenGL pour les calculs généralistes habituellements réservés aux CPU. Il s’agit d’un standard ouvert soutenu par le Khronos Group et supporté par la majorité des cartes graphiques actuelles.

L’API étant en C et les cas d’utilisation étant très spécifiques, elle n’est pas très répandue dans le monde Java.

L’intérêt principal des GPU étant de pouvoir traiter de grand volumes de données par lots de manière très rapide et très parallélisée.

Selon les algorithmes mis en place on peut avoir des gains très importants en faisant faire le calcul par le GPU plutôt que par le CPU.

Il y a cependant de nombreux écueils à éviter dont nous a fait part Olivier, notamment au niveau des temps de transfert entre la RAM et le GPU, le support plus ou moins bon des nombres flottants ou bien que le GPU puisse effectuer plus d’exécution qu’attendu suite à des optimisations internes à celui-ci.

Le format de la présentation (30 minutes), et le fait que je ne connaissais pas en détail OpenCL ne m’ont pas permis de comprendre tous les détails de cette première partie, mais simplement que le gain en performance n’est pas systématique et qu’il y a des contreparties auxquelles il faut faire bien attention en utilisant cette technologie.

Après cette présentation d’OpenCL, Olivier nous a montré JavaCL. Le but de ce framework est de faire un bridge entre le code en C d’OpenCL et du code Java. Pour cela il se base sur un plugin Maven qui génère automatiquement les classes Java nécessaires à l’utilisation du code OpenCL codé en C.

Il faut donc déjà maitriser OpenCL afin d’en tirer partie en Java. Cependant, le framework permet de simplifier beaucoup de facettes d’OpenCL, notamment au niveau de la sélection de l’unité de processing la plus adaptée en fonction de ce qu’on veut faire. En effet, si vous devez faire des calculs précis en virgule flottante, le CPU sera plus adapté que le GPU.

CLContext context = JavaCL.createBestContext();
CLProgram program = context.createProgram(myKernelSource).build();
CLKernel kernel = program.createKernel(
        "myKernel",
        new float[] { u, v },
        context.createIntBuffer(Usage.Input, inputBuffer, true),
        context.createFloatBuffer(Usage.Output, resultsBuffer, false)
);

JavaCL vous permet, soit de choisir le plus rapide, soit celui qui répond le mieux à des critères que vous lui avez fournis. Pour cela il se base sur des tests via OpenCL des différents processeurs disponibles afin de choisir le plus adapté.

La dernière partie, et la plus convaincante à mes yeux, est la présentation de ScalaCL. Cette fois-ci l’approche est différente, il ne s’agit pas de partir du code OpenCL en C, mais d’optimiser Scala afin qu’il tire profit de la puissance de calcul de la carte graphique pour les opérations parallèles en étendant les collections du langages.

import scalacl._
import scala.math._

object Test {
  def main(args: Array[String]): Unit = {
    implicit val context = Context.best // prefer CPUs ? use Context.best(CPU)
    val rng = (100 until 100000).cl // transform the Range into a CLIntRange
    // ops done asynchronously on the GPU (except synchronous sum) :
    val sum = rng.map(_ * 2).zipWithIndex.map(p => p._1 * p._2).sum
    println("sum = " + sum)
  }
}

Cette fois-ci pas de code C, pas de connaissance nécessaire d’OpenCL, simplement des instructions Scala à rajouter dans son code pour lui signaler qu’il doit se baser sur ScalaCL.

ScalaCL se basant sur JavaCL, il permet également de choisir le processeur le mieux adapté à ses besoins très facilement.

En conclusion, j’étais plutôt curieux sur ce que pouvait donner OpenCL porté en Java et j’ai été finalement assez déçu qu’il ne s’agisse que d’un bridge. A l’inverse l’implémentation Scala me parait beaucoup plus intéressante.

Cependant, il ne faut pas oublier que ces deux projets sont en phase expérimentale, et que, bien qu’ils aident grandement à simplifier l’utilisation de l’API OpenCL, ils apportent également d’autres problèmes (problèmes de libération mémoire entre la mémoire de la carte graphique et le garbage collector par exemple). Ni que OpenCL n’est pas une solution magique à tous les problèmes de performances, même pour des traitements hautement parallélisés.

Nombre de vue : 22

AJOUTER UN COMMENTAIRE