2

I have a function that can take a 1d array (double[]) as an argument while my source data is a 2d array (double[,]) of 'cnt' number of 3d points, like so

double[,] points = new double[3,cnt]

But what I actually want to do is to pass on each of the three 2nd dim arrays to the function gpu.Average(double[] arg), preferably without having to copy the content of the arrays value[i] by value[i]. Is that possible in C#?

EXAMPLE CODE

This works:

double[] points1d = new double[cnt];
// ... fill points1d with data, then
double a = gpu.Average(points1d);  // <- Alea.gpu.Average() accepts a 1d array 

But as said, I want to pass on the second dimension to the function gpu.Average() whithout having to run for-loops three times to copy into 1d arrays:

double[,] points2d = new double[3,cnt];
// ... fill points2d with 'cnt' items of data and
// then pass it on

double x = gpu.Average(points2d[0,??]);  // How to pass on 2nd dim?
double y = gpu.Average(points2d[1,??]);     
double z = gpu.Average(points2d[2,??]);     

Is this possible without having to copy the data into 1d arrays?

(BTW, calculating average is not a good example use of gpu parallel library, this is just a test case comparing execution times for different data types & structures).

// Rolf

8
  • 2
    No, but if you use nested arrays ([][]) instead of 2d arrays ([,]), then you can. Commented Jul 21, 2017 at 16:09
  • Hm. but can nested arrays be allocated with dynamic length? I'm thinking of double[3][someList.Count]; Commented Jul 21, 2017 at 16:19
  • If you are extremely lucky then your method will have an overload that takes a double* instead of an array. Then you can do this. Commented Jul 21, 2017 at 16:26
  • They can be allocated however you like, but it's more code than a 2D array. You have to create each array explicitly, so you'd need a for-loop. Commented Jul 21, 2017 at 16:28
  • You can pin the array and overwrite its object header so that it looks like a one-d array of the appropriate length (for the first array). For the later arrays you can do temporary overwrites of the last elements of the prior array and then use some CIL code to reinterpret cast the method table pointer you wrote to a managed reference of 1D array type. Commented Jul 21, 2017 at 16:30

1 Answer 1

2

No this is not possible in managed code without copying the contents of e.g. points2d[1,*] to a new single dimensional array.

In managed code every array has to know its length, so that every index access can be checked and ArrayIndexOutOfBounds exception thrown if the index is out of bounds. The length (integer value) is stored before the first element of the array, so that the runtime knows where to find it. Now with this I guess one can see why you cannot split array into several parts and treat those as new arrays. Note that the story is even more complicated for multidimensional arrays, which have to store the number of dimensions and the size of each dimension...

What you can do is to use jagged array:

double[][] points2d = new double[3][];
points2[0] = new double[cnt];
...
gpu.Average(points2d[0]);

Jagged arrays are faster than multidimensional arrays and are recommended to be used instead of multidimensional arrays even by MS.

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

8 Comments

+1, though it actually is possible to do this with managed code, but the code required to do so is brutal and will crash horribly if a GC happens while the shenanigans are being performed. Of course, you can prevent GC during, but it's not for the faint of heart.
Can you link to a MS reference saying jagged arrays are recommended over multidimensional arrays?
Unfortunately that code doesn't compile. Edit: I will test with double[][] points2d = new double[3][]; though. bb
OK, repeatingly creating the additional three arrays [3][...] works. Which is essentially the same as creating three discrete arrays. In this case all these allocations takes 10 longer than it takes for the CPU to do the job directly, but this trick may prove to be useful in other cases. It works, and so I will accept this as The answer. Thanks a lot! Edit: You could add the last missing square brackets to the code example new double[3][]; though. :)
That reference seems to be talking about only the case where a jagged array would save space; "Suppress a warning from this rule if the multidimensional array does not waste space." - which fits OP's code in this case. Interesting that they have this warning at all though, for such a specific and (I would have thought) unusual case.
|

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.