3

I am having troubles with aligning structs between the host and device in OpenCL. I defined many custom structs on both the host and device, and all of them seem to be working perfectly except for one.

I am sending over two structs in an array. All values in the first struct (sObject[0]) are being read correctly in the device, but the second (sObject[1]) is being read in a seemingly corrupt manner where the values are all mixed up and some are missing.

From what I've read, this is possibly a problem with data alignment where the host and device may have different type allocations or padding, but I have verified that the data types have the same size on both the host and device and I have attempted using alignment such as #pragma pack(8), __attribute__ ((aligned (128))) and __attribute__ ((packed)) although I am unsure if they are working correctly with the compiler (VS2017).

Here is the code for the struct on both the host and device:

Host:

typedef struct _cl_tag_sObject {
    cl_double3 m_vCenter;
    cl_double3 m_vBounds1;
    cl_double3 m_vBounds2;
    cl_double m_dRadius;
    cl_bool m_type;
} sObject;

Device:

typedef struct _cl_tag_sObject {
    double3 m_vCenter;
    double3 m_vBounds1;
    double3 m_vBounds2;
    double m_dRadius;
    bool m_type;
} sObject;

Here are the assigned values on the host and the values read from the device:

Host:

m_vCenter = (0,-100.5,0)
m_vBounds1 = (2,2,2)
m_vBounds2 = (3,3,3)
m_dRadius = 100
m_type = 0

Device:

m_vCenter = (0,0,2)
m_vBounds1 = (2,0,3)
m_vBounds2 = (3,0,100)
m_dRadius = 1
m_type = 0

It seems that the value -100.5 is being omitted and the middle values in (2,2,2) and (3,3,3) are taking the place of padding, although I am new to OpenCL and am unsure as to how this process actually works.

What is causing this problem and how can it be solved?

Thanks.

1 Answer 1

2

WRT struct packing: __attribute__ ((packed)) causes zero padding between struct elements on GCC and LLVM. I don't know if your device's implementation uses them. I have almost no experience with VS, but i think #pragma pack(1) is what you need on host side to get zero padding.

Aside from packing, you need to be aware that the cl_<type>3 types are typedef'ed to cl_<type>4 types in CL/cl_platform.h header. So on the host side, they're essentially the same.

So even with packing, your struct has cl_double4 with 4 elements, and should look like this in host memory (cast to array of doubles):

0 100.5 0 0 | 2 2 2 0 | 3 3 3 0 | 100

I suspect your device's compiler ignores the host convention and uses true 3-element vectors for double3. You can verify simply by changing the device-side struct to use double4:

    double4 m_vCenter;
    double4 m_vBounds1;
    double4 m_vBounds2;

Unfortunately structs are a bit of grey area in OpenCL. Might be best to avoid 3-element vectors inside structs..

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.