Cuda OpenGL Interoperability efficiency problem

I wonder why a way to initialize vbo make a big difference in fps when interacting with cuda. When I create vbo there are two possibilities:

  • vbo reserves only memory space with the given data size (in this case positions of the particles are first time write to vbo within the kernel and later modify in the kernel):
gl.glBufferData(GL3.GL_ARRAY_BUFFER, n_particles * 4 * Sizeof.FLOAT, null, GL3.GL_DYNAMIC_DRAW);
  • vbo reserves memory space with the given data size and get some initial data (positions of the particles - ofcourse these values are later modify in the kernel):
gl.glBufferData(GL3.GL_ARRAY_BUFFER, n_particles * 4 * Sizeof.FLOAT, FloatBuffer.wrap(particlesPositions), GL3.GL_DYNAMIC_DRAW);
  1. ~408 fps

  2. ~75 fps

You can check this behaviour using a Simple OpenGL example from Nvidia GPU Computing SDK.

I assume that in both cases vbo stores vertices in the gpu memory. Can anyone explain what’s going on ?

I believe it is because a GL buffer gets allocated in a lazy-fashion. Its buffer memory is not allocated until it is actually accessed.

If I understand your syntax correctly, in the first case, where you get 408fps, it might be CUDA that allocates the memory as soon as you map it to CUDA.

In the second case, it is OpenGL that allocates the memory.

Obviously it seems to make a difference whether OpenGL or CUDA allocates the memory. Maybe it needs to manually copy the data between the contexts? Try to vary the size (e.g. the number of particles) and see if that affects the mapping costs.

When I change the number of particles the difference is similar: ~710, ~160 or ~1050 , ~280.

I assume that the better the framerate the lower the number of particles. Take the ratios of your two algorithms:

low number of particles: 1050/280 = 3.75
med number of particles: 710/160 = 4.75
hi number of particles: 408/75 = 5.44

The more particles you use, the higher the performance gap becomes. A hidden copy by the driver could exlain, why the ratios are not the same.

Can you try to just time the mapping, i.e. only use the cuda kernel once and then keep the data unchanged?