1
votes

I'd like to implement two versions of my kernel, a vector and a scalar versions. Now I'm wondering whether let's say double4 type is similar in term of memory access to a array of double of size 4.
What I have in mind is to use the same data type for my two kernels where in the scalar one I will just work on each component individually (.s0 .. .s3) like with a regular array.
In other world I'd like to use OpenCl vector types for storage only in the scalar kernel and take the advantage of the vector properties in the vector kernel.
I honestly don't want to have different variable types for each kernel.
Does that make sense to you guys?
Any hints here?
Thank you,

Éric.

3

3 Answers

2
votes

2, 4, 8 and 16 element vectors are laid out in memory just like 2/4/8/16 scalars. The exception is 3 element vectors, which use as much memory as 4 element vectors. The main benefit of using vectors in my experience has been that all devices support some form of instruction level parallelism, either through SIMD instructions like on CPUs or through executing independent instructions simultaneously, which happens on GPUs.

1
votes

Regarding the memory access pattern:

This depends first and foremost on your OpenCL kernel compiler: A reasonable compiler would use a single memory transaction to fetch the data for multiple array cells used in a single work item, or even multiple cells used in multiple items. On NVidia GPUs global device memory is read in units of 128 bytes, which makes it worthwhile to coalesce as many as (Edit:) 32 float values for every read; see

NVidia CUDA Best Pracices Guide: Coalesced Access to Global Memory

So using float4 might not even be enough to maximize your bandwidth utilization.

Regarding the use of vector types in kernels:

I believe that these would be useful mostly, if not only, on CPUs with vector instructions, and not on GPUs - where work items are inherently scalar; the vectorization is over multiple work items.

1
votes

Not sure if I get your question. I'll give it a try with a bunch of general hints&tricks.

You don't have arrays in private memory, so here vectors can come in handy. As is described by the others, memory-alignment is comparable. See http://streamcomputing.eu/blog/2013-11-30/basic-concepts-malloc-kernel/ for some information.

The option you are missing is using the structs. Read the second part of the first answer of Arranging memory for OpenCL to know more.

Another thing that could be handy:

__attribute__((vec_type_hint(vectortype)))

Intel has various explanations: http://software.intel.com/sites/products/documentation/ioclsdk/2013XE/OG/Writing_Kernels_to_Directly_Target_the_Intel_Architecture_Processors.htm

It is quite tricky to write multiple kernels in one. You can use macro-tricks as described in http://streamcomputing.eu/blog/2013-10-17/writing-opencl-code-single-double-precision/