Delphi array conversions between 2D and 1D and back again - arrays

I am doing some work with OpenCL for GPU processing of calculations. OpenCL cannot accept a 2D array passed to it, so my 2D arrays need to be converted to 1D and then back to 2D after processing them.
For 2D to 1D I use code like...
i:=0;
for y:=0 to yDim-1 do
begin
for x:=0 to xDim-1 do
begin
FlatArray1[i]:=Array1[x,y];
FlatArray2[i]:=Array2[x,y];
FlatArray3[i]:=Array3[x,y];
FlatArray4[i]:=Array4[x,y];
FlatArray5[i]:=Array5[x,y];
inc(i);
end;
end;
I can then pass these 1D arrays as parameters to OpenCL. The OpenCL processing time is very fast. Once OpenCL is done the 1D arrays need to be converted back into 2D.
x:=0;
y:=0;
for loop:=0 to 1DArraySize-1 do
begin
Array1[x,y]:=FlatArray1[loop];
Array2[x,y]:=FlatArray2[loop];
Array3[x,y]:=FlatArray3[loop];
Array4[x,y]:=FlatArray4[loop];
Array5[x,y]:=FlatArray5[loop];
inc(x);
if x=xDim then
begin
x:=0;
inc(y);
end;
end;
An example of time ratio is 60 ms for the OpenCL calculations that process the arrays and 550 ms for the array conversion loops.
The 550ms is longer than using CPU alone for calculations so it is killing the advantage OpenCL gives for calculation times.
Are there any clever tricks for more efficiently converting the arrays from 2D to 1D and back again?
Thanks for any ideas.

The fastest conversion is avoiding conversion at all.
You can have one data copy in memory and cast it to one-dimensional or 2D array. But note the x should be the second dimension for consistent data layout. It is not possible if 2D array is dynamic (it does not occupy single memory region).
Simple example without thorough type checking (perhaps OpenCL function needs just address of data):
procedure XX(p:PByteArray);
begin
Inc(p[47]);
end;
type
TArr2D = array[0..5, 0..7] of Byte;
PArr2D = ^TArr2D;
TArr1D = array[0..47] of Byte;
var
A: TArr2D;
begin
A[5,7] := 57;
XX(#A);
Caption := A[5,7].ToString;
Also it is possible to use absolute directive to share the same data, and records with variants where two fields share the same memory too.
procedure YY(var B: TArr1D);
begin
Dec(B[47]);
end;
var
A: TArr2D;
AA: TArr1D absolute A;
begin
A[5,7] := 57;
YY(AA);
Caption := A[5,7].ToString;

Some say that because in Delphi dynamic 2D arrays are declared as array of array of [some type] this is a weakness of language which makes working with them much harder in compared to other programming languages.
Well I disagree. Granted it does require a bit different thinking. In the end this can even be an advantage that is if you do know how to use it. How?
Well when you declare array as array of array of [some type] the outer dimension of this 2D array is actually array of references to 1D array that represent inner dimension of the said 2D array. We can use this to our advantage since we can assign any such reference from the outer dimension of our 2D array to another variable of the same type of inner arrays.
So if you declare your 2D array like:
type
//1D array that will prepresent inner dimension of 2D array
T1DArr = array of Integer;
//1D array that stores references to 1D arrays of inner dimension
//which in fact turns this into 2D array.
T2Darr = array of T1DArr;
you can then work with 2D array in a way you area already familiar with
var
A1DArr: T1DArr; //Declare variable for 1D array
A2Darr: T2DArr; //Declare variable for 2D array
begin
//Set dimension of 2D array
SetLength(A2DArr,10,10);
//Set value to specific item of the 2D array
A2DArr[X,Y] := 15;
But you can then assign reference of any of the inner dimension arrays to separate variable using:
//Assign reference to inner array with index of 1 to 1D array variable
A1DArr := A2DArr[1];
EDIT: But how does this help you in converting your 2D array into one 1D array.
As part of built in functionality to work with arrays Delphi includes ability to easily join multiple dynamic arrays into one. So no need to move data from 2D array into 1D array by accessing each array item individually inside a nested loop.
You can use system System.Concat procedure to join two dynamic arrays together.
Or you can just use add operator like so
A1Darr := A2DArr[0] + A2DArr[1];
This joins inner arrays of 2D array with index 0 and 1 into one 1D array
PS: Another thing that you should change in your code is to work one one array at time. In your code you have nested loop inside which you are working on five different arrays. It would be better to have five separate nested loops one for each array. Why?
When you access first item of an array part of that array is pushed on a stack. But when you access the second item of that array part of the data from that array is already present on stack so access is much faster.
Now this won't work if you are often jumping between different arrays and you would end up pushing data on stack much more often which can in the end hurt performance as it negates purpose of stack.

Related

VB.Net create as many arrays as possible from one array

I have an Array lets say myarray ={1,2,3,4,5,6}
What I'm trying to do:
is generate as many as new arrays by changing each value with a value of the same array
example: myarray[0]=myarray[1] so first array will be {2,2,3,4,5,6}
then myarray[0]=myarray[2] so 2nd array will be {3,2,3,4,5,6}
later myarray[1] = myarray[0] so array will be {1,1,3,4,5,6}
and so on
I tried to think of many solutions but none of them work.

Julia: 2d array assignment

I'm trying to do the assignment in the 2d array with the nested loop. I'm trying to access the elements of the array as follows. But I get a mistake. I've searched, but I didn't get results. How can I assign Julia in the 2d array?
for x in 1:total
for y in 1:W
#show (x, y)
if agirliklar[x] <= y
V[x][y] = getMax(V[x-1][y], degerler[x] + V[x-1][y - agirliklar[x]])
else
print("sa")
V[x][y] = V[x-1][y]
end
end
end
BoundsError: attempt to access 7×6 Array{Int64,2} at index [0]
My code
Error
In Julia arrays are 1-based not 0-based.
You try to access V[x-1] where x can take value of 1.
Site note: always provide a minimum working example (MWE) rather than just dumping a part of your production code.
(At least) two things are wrong here:
As #PrzemyslawSzufel says, ordinary Julia arrays are 1-indexed, so you cannot access them at index zero. Though it is possible to get special arrays that are 0-indexed.
If V is a 2D array, as you are saying, you cannot access it like this: V[x][y]. Instead you access them like this: V[x, y]. You can read more about this here: https://docs.julialang.org/en/v1/manual/arrays/#man-array-indexing-1

How to subtract matrices from elements of cell arrays in a loop?

I have created a cell array of dimensions 1x10, named A. Each element contains a 100x5 matrix. Hence, I got 10 matrices 100x5. However, I want to put every matrix of the cell array into a loop. If B is a 100x5 matrix, C is a 100x1 vector and c is a constant, the loop should look like:
for t=1:100;
j=1:5;
x=c*inv((B(t,j)-A(t,j))*((B(t,j)-A(t,j))')*(A(t,j)-C(t,1)*ones(1,5));
end;
end;
At the end x should deliver a 1x10 cell array that will contain 10 elements of matrices 100x5.
I would appreciate any help. Thank you in advance!
If I understand your question correctly, you are asking how to access a cell array. Let i index the cell array. Then you can access the ith entry of the cell array by calling A{i}. Then your code is:
for i=1:10
for t=1:100
j=1:5
x{i}=c*inv((B(t,j)-A{i}(t,j))*((B(t,j)-A{i}(t,j))')*(A{i}(t,j)-C(t,1)*ones(1,5));
end
end
end
You may want to think about your problem and whether or not you can eliminate the the two middle for loops by writing it in matrix notation. It looks similar to a least-squares estimator, which is (X'X)^(-1)*X'y, but the element-by-element inverse is throwing me off.

Correlation of the positions of a multidimensional array to what they represent during initialization

I first want to clarify if my logic in the following is correct:
In a 2 dimensional array, say A[x][y], x represents the number of braces and y the number of elements in each brace. So int A[2][3] is initialized as:
{
{1,2,3}, //from A[0][0] to A[0][2];
{4,5,6} //from A[1]{0] to A[1][2];
};
Second, I want to know what the similar correlations are in a 3 dimensional array, four dimensional, and so on, and how to know which dimension number correlates to what level for any multi-dimensional array.
For example, in A[3][4][2], does the 3 denote the number of 2d tables, or rows/columns in each table? And in A[2][3][4][5], does 2 represent the number of 2d tables, no. of 3d tables, no. of 1d tables, or no. of rows/columns per 1d table? Note:I'm getting my head around multi dimensional arrays for the first time, please explain as simplistically as possible.
Yes what you say it's correct. You can think that recursively.
Start from a 1D array (let's assume that it has 3 elements):
int 1darray[] = {0, 1, 2};
Now producing a 2D array simply says go inside every element of 1darray and put another 1D array, to produce a 2D one, like this:
int 2darray[] = {1darray_0, 1darray_1, 1darray_2};
where the 1darray_0, 1darray_1, 1darray_2 are 1D arrays, just like the 1darray we created in the start. So now this will form a 3x3 2D array.
Now the 3D array can be formed like this:
int 3darray[] = {2darray_0, 2darray_1, 2darray_2};
where the 2darray_0, 2darray_1, 2darray_2 are 2D arrays, just like the 2darray we created above. So now this will form a 3x3x3 3D array.
Your example:
A[3][4][2]
says that A has:
3 rows
4 columns
2 z-columns
In general however, I would advice you to have in mind the picture I have in my 2D dynamic array (C):
which describes in a nutshell what I tried to explain in the start.
As you increase your dimensions, you replace every element of the previous array with an array of the next dimension, while you reach the end.

Arrays in matlab

I have a structure names eye_record which has 6 fields, one of which is x_pos_measured_deg:[1800x1 double]
I want to declare an array in such a way that using for loop, i can get all values of that specific field into a new array and do some work on them. Can anyone show me how to do that? here is m code:
arr=zeros(1,1800);
for t=1:length(eye_record);
arr(t)= eye_record(t).x_pos_measured_deg;
end
it gives me this error: In an assignment A(I) = B, the number of elements in B and I must be the same. How can i fix this? or how should i declare my array so that it won't give me this error? I want all the objects or values, which are in x_pos_measured_deg field to go into my new array.
Your eye_record is struct, not array, so you can not use indexing with eye_record. Your eye_record.x_pos_measured_deg is array and you have to loop through it. So the loop should be:
arr=zeros(1,1800);
for t=1:length(eye_record.x_pos_measured_deg)
arr(t)= eye_record.x_pos_measured_deg(t);
end
But actually, you can assign values directly like:
arr=zeros(1,1800);
arr = eye_record.x_pos_measured_deg';
since you declared arr to have size of 1x1800, and eye_record.x_pos_measured_deg has size of 1800x1.
Without arr=zeros(1,1800);, then no ' at the end:
arr = eye_record.x_pos_measured_deg;

Resources