Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OpenCL Backend: Argument Mapping #45

Closed
m4rs-mt opened this issue Nov 3, 2019 · 2 comments
Closed

OpenCL Backend: Argument Mapping #45

m4rs-mt opened this issue Nov 3, 2019 · 2 comments
Assignees
Milestone

Comments

@m4rs-mt
Copy link
Owner

m4rs-mt commented Nov 3, 2019

The new CLArgumentMapper maps managed values from the .Net world to the OpenCL driver world. Since we have to map all intrinsic view types (which are an abstract concept) to actual kernel types, the CLTypeGenerator class should do the job for us. However, it is not currently known whether OpenCL drivers accept structures with nested pointer declarations (they will not be passed as pointers but as constants - which should be acceptable...). We need to investigate this issue and change the classes CLArgumentMapper/CLTypeGenerator accordingly (if necessary).

@m4rs-mt m4rs-mt added this to the v0.7 milestone Nov 3, 2019
@m4rs-mt
Copy link
Owner Author

m4rs-mt commented Nov 16, 2019

Unfortunately, it is not possible to pass (global) pointers to OpenCL buffers within structures, since they require a user-defined driver-specific argument mapping (interested readers should refer to this post). In other words, a C# structure

public struct Foo
{
    public ArrayView<int> Data;
    public long SomeField;
}

cannot simply be passed to a kernel by creating a marshalling OpenCL structure (and a corresponding host structure in managed code) View_Int:

struct View_Int
{
    __global int *ptr;
    int length;
}

struct Foo
{
    struct View Data;
    long SomeField;
}

One solution to this problem is to extract all nested ArrayView<> values from the arguments of a kernel. We should extract all source view objects (i.e. CLBuffer instances) and map their values separately with distinct calls to clSetKernelArg. After bringing the buffer pointers into the OpenCL world, we can reconstruct the actual view structures to simulate the intended behavior. Consider the following ILGPU kernel program:

void Kernel(Index index, ArrayView<int> source, Foo foo)
{
     // ...
}

As previously mentioned, this kernel cannot be represented in OpenCL via:

__kernel void Kernel(struct View_Int source, struct Foo foo)
{
    // ...
}

However, to avoid the problems presented, we can output the following OpenCL code:

__kernel void Kernel(
    __global int *ptr1,         // First nested view pointer
    __global int *ptr2,         // Second nested view pointer
    struct View_Int source, // Source structure without pointer information from host
    struct Foo foo)             // Source structure without pointer information from host
{
    // Setup view pointers in kernel code
    source.ptr = ptr1;
    foo.Data.ptr = ptr2;
    // ...
}

@m4rs-mt
Copy link
Owner Author

m4rs-mt commented Nov 27, 2019

Unfortunately, the proposed solution does not work properly, since OpenCL does not allow nested pointers within structures to be passed to the kernel. However, some drivers accept such code, while others simply fail. Therefore, passing arguments requires an interop structure to be passed to the kernel, which stores the required offset and length information for each view. Then, each kernel argument is converted into its internal representation, which can contain (and work on) pointers to device-memory addresses.

@m4rs-mt m4rs-mt self-assigned this Nov 27, 2019
@m4rs-mt m4rs-mt closed this as completed Nov 28, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant