Efficiently sort a column of a two-dimensional array in C - c

I create a 2-dimensional Array in C via malloc like this:
double **x;
x = malloc(rows * sizeof(double*));
for (n = 0; n < rows; n++){
x[n] = malloc(columns * sizeof(double));
memset(x[n], 0, columns * sizeof(double));
}
I also check if malloc failed but for better readibility I posted that version. It actually works fine.
Now I have a function which is qsorting the elements row-wise:
double qsort_row_wise(double points[], int points_count)
Which I can call for a specific row(number 3 / 4th row) with 4+1 columns by:
my_qsort(x[3], 4);
This function is receiving a normal array and is also working well.
Now I want to use this function to qsort a column. That's why I am searching for something like this(which is not working):
my_qsort(x[][3], 4);
x[][3] here means a vector of all elements of the column 3.
If possible I would like to do a "vector"-like operation, not selecting everything step by step(for loop) for best performance.

Since you want a 2D array, it is better to allocate it as a single contiguous block:
double *x = calloc(rows * columns, sizeof(double)); // does zero init
Now you can index using arithmetic, so your my_qsort function should be declared like this:
void my_qsort(double *start, size_t count, size_t stride);
Now to sort row 3 you can do this:
my_qsort(x + 3 * columns, columns, 1);
And to sort column 5 you can do this:
my_qsort(x + 5, rows, columns);
During the sort, the elements you need to access are start[ii * stride], where ii goes from 0 to count. And start of course is simply the first cell in the 2D array that you wish to sort--typically either the leftmost cell in a row or the top cell in a column. It is also possible to use the same function to sort part of a row or column, or to sort an arbitrary "line" through the matrix, e.g. the diagonal of a square matrix:
my_qsort(x, rows, columns + 1);
Having a single allocation to store your 2D array not only makes "strided" operations easier, it is also more efficient, because it reduces the number of allocations, improves spatial locality, and on Linux, increases the chances that the memory will be instantly reclaimed when you free it, because "large" allocations are done via mmap rather than sbrk.

Well, you need to create an array the size of how many rows you have since a columns consists of n rows.
double *cols = malloc(nofrows * sizeof(double));
then loop through the 2 dimensional array over the rows and use the column index as a constant:
int whichcolumn = 1;
for (int i = 0; i < rows; i++)
cols[i] = x[i][whichcolumn];
then pass cols to the qsort function
qsort_row_wise(cols, nofrows);

If possible I would like to do a vector-operation, not selecting everything step by step(for loop) for best performance.
This is not possible.
What your 1st code snippet creates isn't a 2D-array, but one 1D-array of pointers, with each element pointing to a 1D-array of doubles. Such a construct sometimes is called a "scattered" array, as it consists of "number of rows"+1 not necessarily continuous blocks of memory.
Concluding from the latter fact, you cannot extract a column, as the elements are distributed throughout the memory and cannot be addressed by a single operation.

Related

Multidimensional array from text file

Im looking for a way to fill up a multi-d array with numbers gotten from a text file.
I have an array(?) dynamically created, but im not sure how to make it multidimensional.
basically the text document has a set of numbers, user input decides the amount of columns and rows of a matrix, and i need to fill that matrix with numbers from the text document. Any help is appreciated
ptrm2 = (int*)malloc(size2 *sizeof(int));
You can allocate a two-dimensional array in two stages, as follows (I'm assuming that the base data type is int here, but it could be almost anything):
int** my2dArray = malloc(sizeof(int*) * n_rows); // Makes one INTEGER POINTER for each of n_rows
for (int n = 0; n < n_rows; ++n) my2dArray[n] = malloc(sizeof(int) * n_cols); // Makes one INTEGER for each column
You can then access any element of the 2-D array, given its row and column with, for example:
int value = my2dArray[row][column];
Here, I've assumed the conventional (standard) approach of using "row priority" (so that the first index is the row).

copying 2d array of type (double **2darray) to GPU using cuda [duplicate]

I am looking into how to copy a 2D array of variable width for each row into the GPU.
int rows = 1000;
int cols;
int** host_matrix = malloc(sizeof(*int)*rows);
int *d_array;
int *length;
...
Each host_matrix[i] might have a different length, which I know length[i], and there is where the problem starts. I would like to avoid copying dummy data. Is there a better way of doing it?
According to this thread, that won't be a clever way of doing it:
cudaMalloc(d_array, rows*sizeof(int*));
for(int i = 0 ; i < rows ; i++) {
cudaMalloc((void **)&d_array[i], length[i] * sizeof(int));
}
But I cannot think of any other method. Is there any other smarter way of doing it?
Can it be improved using cudaMallocPitch and cudaMemCpy2D ??
The correct way to allocate an array of pointers for the GPU in CUDA is something like this:
int **hd_array, **d_array;
hd_array = (int **)malloc(nrows*sizeof(int*));
cudaMalloc(d_array, nrows*sizeof(int*));
for(int i = 0 ; i < nrows ; i++) {
cudaMalloc((void **)&hd_array[i], length[i] * sizeof(int));
}
cudaMemcpy(d_array, hd_array, nrows*sizeof(int*), cudaMemcpyHostToDevice);
(disclaimer: written in browser, never compiled, never tested, use at own risk)
The idea is that you assemble a copy of the array of device pointers in host memory first, then copy that to the device. For your hypothetical case with 1000 rows, that means 1001 calls to cudaMalloc and then 1001 calls to cudaMemcpy just to set up the device memory allocations and copy data into the device. That is an enormous overhead penalty, and I would counsel against trying it; the performance will be truly terrible.
If you have very jagged data and need to store it on the device, might I suggest taking a cue of the mother of all jagged data problems - large, unstructured sparse matrices - and copy one of the sparse matrix formats for your data instead. Using the classic compressed sparse row format as a model you could do something like this:
int * data, * rows, * lengths;
cudaMalloc(rows, nrows*sizeof(int));
cudaMalloc(lengths, nrows*sizeof(int));
cudaMalloc(data, N*sizeof(int));
In this scheme, store all the data in a single, linear memory allocation data. The ith row of the jagged array starts at data[rows[i]] and each row has a length of length[i]. This means you only need three memory allocation and copy operations to transfer any amount of data to the device, rather than nrows in your current scheme, ie. it reduces the overheads from O(N) to O(1).
I would put all the data into one array. Then compose another array with the row lengths, so that A[0] is the length of row 0 and so on. so A[i] = length[i]
Then you need just to allocate 2 arrays on the card and call memcopy twice.
Of course it's a little bit of extra work, but i think performance wise it will be an improvement (depending of course on how you use the data on the card)

C extract an array from a matrix using pointers

I wrote a code and I have some data stored in a 2d matrix:
double y[LENGTH][2];
I have a function that take as input a 1D array:
double function(double* data)
I am interested in passing the data stored in the first column of this matrix to this function. How can I do that using pointers?
My function is something like (where the array data is an array of double containing LENGTH elements:
double data[LENGTH];
):
double function(double* data){
double result=0;
for(int i=0; i<LENGTH; i++){
result+=data[i];
}
return result;
}
And I want to pass to this function a row of a matrix as data input.
Thanks to everyone in advance!
If you pass a pointer to the first element of your 2D matrix, you can access it as a 1 D matrix since the elements are stored contiguously:
double y[LENGTH][2];
x = function(y[0]);
...
double function(double* p) {
int ii;
double sum=0;
for(ii=0; ii<2*LENGTH; ii++) sum += p[ii];
return sum;
}
Note that in this case the order of accessing the elements is
y[0][0]
y[0][1]
y[1][0]
y[1][1]
y[2][0]
... etc
update - you just clarified your question a little bit. If you want to access just one column of data, you need to skip through the array. This means you need to know the size of the second dimension. I would recommend something like this:
double function(double* p, int D2) {
int ii;
double sum=0;
for(ii=0; ii<D2*LENGTH; ii+=D2) sum += p[ii];
return sum;
}
And you would call it with
x = function(y[colNum], numCols);
Now we start at a certain location, then, skip forward D2 elements to access the next element in the column.
I have to say that this is rather ugly - this is not really how C is intended to be used. I would recommend wrapping things into a class that handles these things for you cleanly - in other words, switch to C++ (although it's possible to write pure C functions that "hide" some of this complexity). You could of course copy the data to another memory block to make it contiguous, but that's usually considered a last recourse.
Be careful that you don't end up with code that is unreadable / unmaintainable...
further update
Per your comment, the above is still not what you wanted. Then I recommend the following:
double *colPointer(double *p, int rowCount, int colCount) {
double *cp;
int ii;
cp = malloc(rowCount * sizeof *cp);
for(ii=0; ii<rowCount; ii++) cp[ii] = *(p + ii * colCount);
return cp;
}
This will return a pointer to a newly created copy of the column. You call it with
double *cc;
cc = colPointer(y[colNum], LENGTH, 2);
answer = function(cc);
And now you can use cc in the way you wanted. If you have to do this many times you might be better off transposing the entire array just once - that way you can pass a pointer to a row of the transpose and achieve your result. You can adapt the code above to generate such a transpose.
Note that there is a risk of memory leaks if you don't clean up after yourself with this method.
the question is that do you consider to be the row-dimension.
usually the first one is rows and the second one cols.
that means that your double y[LENGTH][2]; is a matrix with LENGTH rows ans 2 cols.
if that is also your interpretation then the answer to your question is "you can't" since the memory is layed out like this:
r0c0 r0c1 r1c0 r1c1 r2c0 r2c1 ...
you can retrieve pointer to a row but not to a column.
matrix classes are usually designed in a way, that row and column step length is stored so that by carefully setting them you can build sub matrices on a big data chunk.
you may look for opencv matrix implementation if you plan to perform complexer tasks.
if you can change the implementation of the function you want to call. you can change it to accept the row step (number of your columns), so that it does not joust increment the pointer by one to reach the next element but to increment the pointer by row step.
as an alternative there is the obvious way to copy the required column to a new array.
edit:
fixed stupid error on memory layout diagram

Delete a column from a double array

I'm stuck here. I've got a matrix of size NxN stored in a double array. Then I want to delete a given column, lets say the first column. So I created a new double array of size NxN-1 and copy the values from the first matrix to the second one, except the 1st column of course. But then I want to set the first array to be the second array. I am blanking here.
double matrix[N][N]
//fill up the matrix code here...
// remove first column of array
double newMatrix[N][N-1];
for(i = 0; i < N; i++){
for(j = 1; j < N; j++){
newMatrix[i][j-1] = matrix[i][j];
}
}
matrix = newMatrix; // how do I set this correctly? Do I need to realloc the first array?
You cannot assign arrays in C, which I assume that your compiler tells you. To do such dynamic memory management, you will need to use pointers instead of arrays. I suggest you read up on how malloc() and free() work so that you can do what you want.
Edit:
Another solution comes to mind if you are only removing columns (or rows): keep track of the number of rows and columns used in the array. Then you can remove a row or column within the original array without creating a copy first. Just move the data past the delete column (or row) to the left (or up) then decrement your size counters. (I hope this make sense. If not let me know and I'll elaborate.)
like Code-guru said malloc() and free() should help alot, but if u simply wanted to delete the last column the you wouldn't need two arrays:
double matrix[2][3] = {1,2,3,4,5,6}; //declaring a 2 by 3 matrix
for (i=0;i<2;i++) //rows
{
for (j=0;j<3-1;j++) //columns - 1
{
printf("%.1f ",matrix[i][j]); //I chose to display matrix...
}
printf("\n");
}
Instead of accessing elements from array[i][j], one might opt to access elements from array + stride_x[x] + stride_y[y]; where array is originally introduced as double matrix[N*N]; or double *matrix = malloc(sizeof(double)*N*N);.
The stride_y[x] would originally contain offsets of columns for all rows: 0 1 2 3 4 ... N-1 and stride_y[y] would contain similar offsets multiplied with original row width 0 N 2*N 3*N..
From these 1-D arrays one can more effortlessly delete or exchange complete rows and columns, which may come handy in eg. recursive implementation of determinant calculation / Gauss Jordan elimination.

How to find a subset of a 2d array by selecting rows and columns in c?

In an (m by n) array stored as double *d (column major), what is the fastest way of selecting a range of rows and or columns:
double *filter(double *mat, int m, int n, int rows[], int cols[]);
invoked as:
double *B;
int rows[]= {1,3,5}; int cols[]={2,4};
B = filter(A, 5, 4, rows, cols);
which is expected to return a 3-by-2 subset of A consisting of elements (1,2), (1,4), (3,2)...
c provides no native support for this, so you'll have to find a library that supports it, or define it by hand.
pseudocode:
a=length of rows // no built in c functionality for this either,
b=length of cols // use a sentinel, or pass to the function
nmat = allocate (sizeof(double)*a*b) on the heap
for (i=0; i<a; ++i)
for (j=0; j<b; ++j)
// Note the column major storage convention here (bloody FORTRAN!)
nmat[i + j*b] = mat[ rows[i] + cols[j]*n ];
return nmat
// caller responsible for freeing the allocated memeory
I've commented on the two big problems you face.
I'm pretty sure that m and n should be the dimension of the new array (i.e. m should be the number of items of rows and n should be the number of items in cols) and not the dimension of the source array as seems to be the case in your example because a) you don't need to know the dimension of the source array if you already know which indices to pick from it (and are presumably allowed to assume that those will be valid) and b) if you don't know the size of rows and columns they are useless as you can't iterate over them.
So under that assumption the algorithm could look like this:
Allocate memory for an m x n array
For each i in 0..m, j in 0..n
B[i,j] = A[ rows[i], cols[j] ];

Resources