Finally I’m in the local Starbucks, my cappuccino is ready, looks like it’s a perfect time to remember one of the greatest adventures of this year so far – JavaZone 2018!
When earlier this year, in May, I have received this email telling me that my talk “Java and the GPU: unlock the massive performance” was accepted for this year’s edition of JavaZone in Oslo, Norway, I literally jumped out of mu chair shouting out “Yes!!!”.
Visiting this conference was definitely one of my dreams, I’ve heard so many good words about it! Now finally this dream came true. Huge thanks to the committee for accepting my talk!
Finally September has arrived, I’ve landed in Oslo and literally fell in love with Norway from the first site!
An express train brought me from the airport directly to the Oslo central station for only 19 minutes. You may ask – so what? Actually the airport is about ~60 km away from the city and we were cruising with more 220 km/h. And those trains are scheduled to make this route every 10 min. This so cool!
For this conf choosing the train was the best choice, as the venue – Spectrum arena is just next to the central station. The hotel was there as well. So we were perfectly located.
Oslo welcomed us with a grey rainy weather
But just 20 min later it was beautiful and sunny, like in every northern town
In the evening we were invited to the speakers dinner that took place in a beautifully located restaurant with some stunning views of Oslo!
Oh, thats Chris Thalinger also making some photos of this wonderful sunset. By the way it’s raining.
Definitely a wonderful place to relax before the conference. We stayed there until late.
The next day was the first day of the conference. The first thing I saw was the looooong queue of the attendees.
The good (or may be the bad) part was that my talk was scheduled on for the second day. So the first day I had a chance to explore a little bit.
The conference organisation, or I may even say “architecture” is totally different from all other conferences I have attended. The venue is a huge arena, where big concerts take place. There is a big central area where you can find a lot of software company’s booths.
Just take a look how big is it and how many people are in!
The conference kick-off was lovely with some guitar players

The coolest part is that practically all the booth serve their own food all day long! Yes, yes.. you can have food all the time, all day long.. all two days! There was only one major problem for me – I couldn’t taste it all! I haven’t had enough capacity! Definitely OMG.
But not only food, but tons of other cool activities
One of the unique features of JavaZone are the 8 parallel tracks. Yep, 8! That’s a lot! The rooms are themselves not very big, but that makes the cozy.
That’s me attending Vlad Mihalcea’s great talk.
And like every conference the main reward is actually meet and talk to people! Hey, that’s Chris (..and Doug)!
My good friends Simon, Simon, Phillip and my new friend Jennifer
Finally could meet Sharat Chander in person!
Awesome hardcore JVM company of Doug, Volker and Steve
The discussions we had were really useful to me!
At the end of the day we had a wonderful hangout with David, Vincent and Matthew
Then actually came the funny part. My talk was scheduled for 9.00 the next morning. I was sincerely wondering who will ever be interested in GPUs and massive parallel computation so early in the morning? I was a bit nervious wen my talk was approaching.
But I was ready!
So I was expecting a maximum audience of 3 people to show up. What was my surprise when I found my room fully packed!
Oh My God! Absolutely unexpected!
I sincerely want to thank everybody that came. I hope the talk useful and fun to you!
By the way, it became available just few hours later in vimeo! Cool organisation at JavaZone!
When I was done with my talk I took the chance to hang around the beautiful city of Oslo!
Definitely a beautiful capital!
JavaZone 2018 was a great new experience for me! I’ve seen a cool organisation, met great friends and made great ones!
I want to say huge thanks to Rafael, Rustam, Mark and all the team for having me and making this conf a blast!
At the end as always my best five IMHO sessions of the conf from those I was able to see myself live:
Now I’m on may way watching the other talks I’ve missed (and those I’m able to understand)! They are just great!!!
So good bye Oslo! Thank you for being awesome! Hope to see you again!
]]>
But this year was quite a DE(VOXX)ED for me! First I had a chance to speak in wonderful Romania, then beautiful Vienna, after that amazing Lugano, then the loveliest Krakow, finally at the huge Antwerp event! In between I also gave some talks in my home towns Sofia –Java2Days and St. Petersburg – Joker! Let’s not forget that I was in the dreamteam of 5 to organize and run the coolest jPrime conf!
Quite an intense year!!!
So finally this weekend I had some time just to play. Of course play with coding!
As may be some of you saw, I’m really interested in the Nashorn engine to run JavaScript on JVM. I gave once some talks about it!
But not only this bothers me! For several years I’m interested in General Purpose computations on Video Cards (GPGPU)! I even gave some introductory talks on how to use GPU and Java together.
On Devoxx in English:
https://www.youtube.com/watch?v=BjdYRtL6qjg
And on Joker in Russian will be hopefully available soon 
But! What will happen if actually unite these two my passions? How to run some code on the GPU but submitted from.. JavaScript!!!
You will say just use WebCL! But, isn’t it a little bit not ready yet? And as far as I know it is not exactly a full binding to OpenCL but mainly browser oriented stuff. Please correct me if I’m wrong. I’ve even played with some experimental drafts.
What if I want to utilize the full control of our computations on GPU through JS and make it very dynamic?
Yes, yes!! Nashorn is here to help us! And yes, we have the full power of the available bindings like those provided by JOCL!
So let’s do it! The usual example with vector add will be just cool enough!
That’s the JavaScript code:
print("GPU in JS!")
//some typedefs
var String = java.lang.String;
var System = java.lang.System;
var CL = org.jocl.CL;
var Pointer = org.jocl.Pointer;
var Sizeof = org.jocl.Sizeof;
var cl_command_queue = org.jocl.cl_command_queue;
var cl_context = org.jocl.cl_context;
var cl_context_properties = org.jocl.cl_context_properties;
var cl_device_id = org.jocl.cl_device_id;
var cl_kernel = org.jocl.cl_kernel;
var cl_mem = org.jocl.cl_mem;
var cl_platform_id = org.jocl.cl_platform_id;
var cl_program = org.jocl.cl_program;
var LongArray = Java.type("long[]");
var ByteArray = Java.type("byte[]");
var FloatArray = Java.type("float[]");
var StringArray = Java.type("java.lang.String[]");
var IntArray = Java.type("int[]");
var ClPlatformIdArray = Java.type("org.jocl.cl_platform_id[]");
var ClDeviceIdArray = Java.type("org.jocl.cl_device_id[]");
var ClMemArray = Java.type("org.jocl.cl_mem[]");
//helper function
function getString(device, paramName) {
var size = new LongArray(1);
CL.clGetDeviceInfo(device, paramName, 0, null, size);
var buffer = new ByteArray(size[0]);
CL.clGetDeviceInfo(device, paramName, buffer.length, Pointer.to(buffer), null);
return new String(buffer, 0, buffer.length-1);
}
//this goes to GPU
var programSource =
"__kernel void "+
"sampleKernel(__global const float *a,"+
" __global const float *b,"+
" __global float *c)"+
"{"+
" int gid = get_global_id(0);"+
" c[gid] = a[gid] + b[gid];"+
"}";
var start= System.currentTimeMillis();
var n = 1024;
var srcArrayA = new FloatArray(n);
var srcArrayB = new FloatArray(n);
var dstArray = new FloatArray(n);
for (var i=0; i<n; i++){
srcArrayA[i] = i;
srcArrayB[i] = i;
}
var srcA = Pointer.to(srcArrayA);
var srcB = Pointer.to(srcArrayB);
var dst = Pointer.to(dstArray);
var platformIndex = 0;
var deviceType = CL.CL_DEVICE_TYPE_ALL;
var deviceIndex = 2;
CL.setExceptionsEnabled(true);
var numPlatformsArray = new IntArray(1);
CL.clGetPlatformIDs(0, null, numPlatformsArray);
var numPlatforms = numPlatformsArray[0];
var platforms = new ClPlatformIdArray(numPlatforms);
CL.clGetPlatformIDs(platforms.length, platforms, null);
var platform = platforms[platformIndex];
var contextProperties = new cl_context_properties();
contextProperties.addProperty(CL.CL_CONTEXT_PLATFORM, platform);
var numDevicesArray = new IntArray(1);
CL.clGetDeviceIDs(platform, deviceType, 0, null, numDevicesArray);
var numDevices = numDevicesArray[0];
//just print out the name
var devices = new ClDeviceIdArray(numDevices);
CL.clGetDeviceIDs(platform, deviceType, numDevices, devices, null);
var device = devices[deviceIndex];
var deviceName = getString(device, CL.CL_DEVICE_NAME);
print("Device: "+deviceName);
var devices = new ClDeviceIdArray(1);
devices[0]=device;
var context = CL.clCreateContext(
contextProperties, 1, devices,
null, null, null);
var commandQueue =
CL.clCreateCommandQueue(context, device, 0, null);
var memObjects = new ClMemArray(3);
memObjects[0] = CL.clCreateBuffer(context,
CL.CL_MEM_READ_ONLY | CL.CL_MEM_COPY_HOST_PTR,
Sizeof.cl_float * n, srcA, null);
memObjects[1] = CL.clCreateBuffer(context,
CL.CL_MEM_READ_ONLY | CL.CL_MEM_COPY_HOST_PTR,
Sizeof.cl_float * n, srcB, null);
memObjects[2] = CL.clCreateBuffer(context,
CL.CL_MEM_READ_WRITE,
Sizeof.cl_float * n, null, null);
var ps = new StringArray(1);
ps[0] = programSource;
var program = CL.clCreateProgramWithSource(context,
1, ps, null, null);
CL.clBuildProgram(program, 0, null, null, null, null);
var kernel = CL.clCreateKernel(program, "sampleKernel", null);
CL.clSetKernelArg(kernel, 0,
Sizeof.cl_mem, Pointer.to(memObjects[0]));
CL.clSetKernelArg(kernel, 1,
Sizeof.cl_mem, Pointer.to(memObjects[1]));
CL.clSetKernelArg(kernel, 2,
Sizeof.cl_mem, Pointer.to(memObjects[2]));
var global_work_size = new LongArray(1);
global_work_size[0] = n;
var local_work_size = new LongArray(1);
local_work_size[0] = 1;
// Execute the kernel
CL.clEnqueueNDRangeKernel(commandQueue, kernel, 1, null,
global_work_size, local_work_size, 0, null, null);
CL.clEnqueueReadBuffer(commandQueue, memObjects[2], CL.CL_TRUE, 0,
n * Sizeof.cl_float, dst, 0, null, null);
CL.clReleaseMemObject(memObjects[0]);
CL.clReleaseMemObject(memObjects[1]);
CL.clReleaseMemObject(memObjects[2]);
CL.clReleaseKernel(kernel);
CL.clReleaseProgram(program);
CL.clReleaseCommandQueue(commandQueue);
CL.clReleaseContext(context);
print("Calculated on GPU:");
for (var i=0; i<n; i++){
print(srcArrayA[i], " + ",srcArrayB[i]," = ",dstArray[i]);
}
print("Done in: "+(System.currentTimeMillis()-start)+" ms.");I just put it all in jscl.js file.
As you in the beginning I’ve added some type definition shortcuts just to make code look more readable.
To run it in the console I just put:
jjs -cp ./lib/JOCL-0.1.9.jar -scripting jscl.js
JJS is available by default if you have minimum Java 8 installed.
The JOCL jar you can just get from their site.
And what we have (on my Mac):
GPU in JS! Device: GeForce GT 650M Calculated on GPU: 0 + 0 = 0 1 + 1 = 2 2 + 2 = 4 .... 1019 + 1019 = 2038 1020 + 1020 = 2040 1021 + 1021 = 2042 1022 + 1022 = 2044 1023 + 1023 = 2046 Done in: 704 ms.
Isn’t this lovely!!
Funny fact that is that because of the memory latency it about 700 ms no matter if I make 1k computations or 100m of them 
Still, this may be good example of how Java/JVM can be a kind of a technology glue. Having in mind that there are more than 40 languages running on JVM, all of them can benefit from the de facto standard libraries already available for Java.
This is so much cool!! Have Fun!
]]>