4 Replies Latest reply on Jan 21, 2011 6:33 PM by LeeHowes

    How can I use user made funcions in a OpenCL Kernel ?

    char86

      Hello Guys.

      inside my kernel I have a local memory storage:

      __local float Uin[Xmax][Ymax]

      Now i want to make mathimatical differentials with data from __local Uin. I want this many many times in my code so I want to make it with a funcion.

      But i get these errors --------------------------------------------------------------

      OpenCL Compile Error: clBuildProgram failed (CL_BUILD_PROGRAM_FAILURE).

      Line 8: error: expression must
                have pointer-to-object type
            OUT = IN[ 4*XL + i + 2 ][ YL ] - IN[ 4*XL + i ][ YL ];
                       ^

      Line 8: error: expression must
                have pointer-to-object type
            OUT = IN[ 4*XL + i + 2 ][ YL ] - IN[ 4*XL + i ][ YL ];
                                                            ^

      Line 209: error: argument of
                type "local float (*)[4]" is incompatible with parameter of type
                "local float *"
                BUFX = DIFFX(XL, i, YL, UinLOC );
                                                       ^

      3 errors detected.

       

      ---------------------------------------------------------------------------

       

       



      // My Funcion // float DIFFX(int XL, int i, int YL, __local float *IN ) { float OUT; OUT = IN[ 4*XL + i + 2 ][ YL ] - IN[ 4*XL + i ][ YL ]; return(OUT); } // My code inside Kernel to call it // define LS 4 __local float UinLOC[ LS+2 ][ LS ]; BUFX[i] = DIFFX(XL, i, YL, UinLOC );

        • How can I use user made funcions in a OpenCL Kernel ?
          Jawed

          In the DIFFX function, the parameter:

          __local float *IN

          should be:

           __local float **IN 

          or:

           __local float *IN[LS] (you have to move the #define LS higher in your code) 

          The compiler still warns for both of these(not sure why), but the code compiles. You might be better off defining UinLOC as one-dimensional:

          __local float UinLOC[ (LS+2) * LS ];

           and computing the addresses as:

             OUT = IN[ (4*XL + i + 2 ) * LS + YL ] - IN[ (4*XL + i) * LS + YL ];

            • How can I use user made funcions in a OpenCL Kernel ?
              char86

              Thank you.

              The first way compiles, but it gives me wrong numbers.

              The second way is to hard, cause i must change many lines of code, so i think i will use the easy known way.

              Thanks again.

              • How can I use user made funcions in a OpenCL Kernel ?
                rick.weber

                I think the problem is that you're trying to use 2D indexing from a pointer type. To use 2D array, you have to know how many elements are in the leading dimension. While Fortran passes this information off to functions behind the scenes, C (and hence OpenCL) does not. As such, you'll need to explicitly pass the leading dimension of UinLoc to DIFFX() in another parameter and a 1D array lookup. Since C is row-major, DIFFX should look up values as

                OUT=IN[4*XL+i+2 + YL*ld] - IN[4XL + i + YL*ld];

                where ld is the leading dimension parameter you need to add to DIFFX. ld in this case is 4, since array dimensions go from right to left.

                  • How can I use user made funcions in a OpenCL Kernel ?
                    LeeHowes

                    Generally I've always advised people against pretending that C has 2D arrays in their code. Invariable it wrecks code maintenance because of all the sizes you have to pass statically to things, or if you pass a ** you still need the size anyway. Generally I'd stick with 1D arrays and sizes in code like this, it's less messy if you always do it that way and more flexible.