Passing a 2D Array to CUDA Device and Using it [duplicate] - c++

This question already has answers here:
How can I add up two 2d (pitched) arrays using nested for loops?
(2 answers)
Closed 8 years ago.
I have a problem related to CUDA. I create a array which is 2D with :
char **WordMatrix = new char*[N]; // M and N set by the user
for(int i = 0; i < N; ++i)
{
WordMatrix[i] = new char[M];
}
I fill the array with a loop. After that where my problem is lying : I can't managed to allocate the memory in device and copy from host to device.
I saw other questions related to this but I did not understand the logic.
Like in this topic : https://devtalk.nvidia.com/default/topic/410182/double-pointer-allocation/ or in here.
I want to understand how to do it with an code example which uses cudaMemcpy and cudaMalloc and 2D Array also explanation of why we need supporting(if you use the approach in the link) pointer?

My understanding is CUDA accepts only linearized 2D arrays, so really a 1D array.
int *my_array = new int[height*width];
for (int h = 0; h < height; h++){
for (int w = 0; w < width; w++)
my_array[width * h + w] = value;
}
You can then copy that to device memory as in the other answer.
Also, this question has more info:
Allocate 2D Array on Device Memory in CUDA.

Create your 2D array in one piece new char[N*M]
Allocate the same amout of memory on GPU cudaMalloc(... sizeof(char)*N*M)
Copy your CPU memory (1.) to GPU (2.) with cudaMemcpy(... hostToDevice)

Related

How do I declare MULTIPLE 2d arrays in C++ using new?

There is a similar topic about this.
How do I declare a 2d array in C++ using new?
What I want to do is to create multiple 2d arrays according to some integer which determines how many 2d arrays there should be.
I want to create a single dimensional array first for pointers and assing every pointer to a multidimensional array, using new. But it seems like you can't ask for memory to create multidimensional array. Why can't we just write:
int** howManyPointers = new int*[translate];
for (int i = 0; i < translate; i++){
howManyPointers[i] = new char[rowsUsed][2000];
}
In my project, 2d array must have 2000 columns but row size is undetermined first. It will be given by the user. Assume you've already got it [rowsUsed]
So what?
You allocate array of pointers, and then for each pointer you allocate 1d array like this:
int** 2dArray = new int*[rows];
for (int i = 0; i < rows; ++i) {
2dArray[i] = new int[cols];
}
and then you can do 2dArray[X][Y] for each X < rows and Y < cols;

Storing a 3D VLA on heap

I need to store an array on heap since I got a seg fault when running the program, due to it being too large. Normally this would be easy, but in this case it is a multidimensional array (3D specifically) and it's a variable length array too.
I tried to fit this answer for a 2D array (which I'm pretty sure works because I found it on another answer on SO) into one for a 3D array
int **ary = new int*[sizeY];
for(int i = 0; i < sizeY; ++i) {
ary[i] = new int[sizeX];
}
by doing this:
double **isoarray = new double*[nBinsX];
for(int xi = 0; xi < nBinsX; ++xi){
isoarray[xi] = new double[nBinsY];
for(int yi = 0; yi < nBinsY; ++yi){
isoarray[xi][yi] = new double[nShuffles];
}
}
Where I should mention that the array is meant to have dimensions nBinsX x nBinsY x nShuffles, but it isn't working, nor did I really think it would to be honest. Can anyone offer a suggestion on how I would do this? Thanks in advance!
Rather than heap-allocating arrays of pointers to more heap-allocated arrays and so on, you should make a single giant allocation and do appropriate indexing. This is a common technique:
double *isoarray = new double[nBinsX * nBinsY * nShuffles];
If you want to make a nice C++ solution out of it, store that pointer in a class which has an indexing method something like this:
double& at(x, y, shuffle) {
return isoarray[x * nBinsY * nShuffles + y * nShuffles + shuffle];
}
This way you have a single contiguous allocation which is better for performance when allocating, when using, and when deallocating. You can play with the indexing in terms of which dimension comes "first" to achieve even better performance depending on which way you usually traverse the data.

Converting linear array to a bidimensional array of structs using pointers

EDIT: I will improve this question. I will clarify it right in a little days.
first, I am writing a litlle bmp image analyzer. I have the following problem: The image is stored on plain bytes, without format as an array.
The image is 24 bits, and requires 3 bytes per pixel. I have tried with a solution that I have found on this stackoverflow page, but I can not adapt it for structures.
I have tried but it references invalid areas and bytes. Here's my complete code if you want to see it in TinyPaste (just for a better highlighting): The code in TinyPaste
EDIT 1: This code is in C++, I want to translate it to pure C for portability reasons. This is just the example from I taken the idea of convert a linear array to bidimensional. I have tried to adapt it to pure C for structs but I fail.
This snippet was taken from a stackoverflow question that made me think about this
//The resulting array
unsigned int** array2d;
// Linear memory allocation
unsigned int* temp = new unsigned int[sizeX * sizeY];
// These are the important steps:
// Allocate the pointers inside the array,
// which will be used to index the linear memory
array2d = new unsigned int*[sizeY];
// Let the pointers inside the array point to the correct memory addresses
for (int i = 0; i < sizeY; ++i)
{
array2d[i] = (temp + i * sizeX);
}
// Fill the array with ascending numbers
for (int y = 0; y < sizeY; ++y)
{
for (int x = 0; x < sizeX; ++x)
{
array2d[y][x] = x + y * sizeX;
}
}
I adapt it to reference structs, but it fails. I have tried multiplying by three in this line:
array2d[i] = (temp + i * sizeX /* multiply by 3*/);
But it still without work. I have also done the related castings from char to the struct bmp_pixel(char r, char g, char b).
Can somebody tell me how to adapt it to pure C for structs?? Thanks.

Access an element of a 2d dynamic array--c++

I created a dynamic array.
typedef float* DynamicMatrix[MAT_SIZE];
DynamicMatrix matDyn;
// allocate rows and initialize to 0
for (r = 0; r < MAT_SIZE; r++) {
matDyn[r] = new float[MAT_SIZE];
for (c = 0; c < MAT_SIZE; c++) {
(matDyn[r])[c] = 0; // IS THIS CORRECT???
}
}
The whole idea was that I create an array of pointers which is my spine of a matrix I am creating. This spine is the leftmost-vertical part of the matrix. Each row of this array will point to another array of floats, therefore making it a dynamic 2d array.
I am unsure how to access an element of this matrix. Please let me know how to.
You can access it just like a "normal" matrix:
matDyn[r][c].
You can just access it by stating matDyn[r][c]
My error was that later in my program(not shown), I was trying to set matDyn[MAT_SIZE][MAT_SIZE] which isn't possible (it can only be matDyn[MAT_SIZE-1][MAT_SIZE-1]) and that is why I was getting my segmentation error.

C++ - dynamic array in 1D works, the same in 2D doesn't work [duplicate]

This question already has answers here:
How to create 2d array c++?
(5 answers)
Closed 9 years ago.
I have a problem with my code. I have some input for the class, the nmax und mmax. These are defined in header as
int nmax;
int mmax;
Then I have some arrays, defined in header as
double* Nline;
double** NMline;
and then I would like to allocate them in the main program. First, I assign to nmax und max a value from the input
nmax = nmax_in;
mmax = mmax_in;
and then I allocate the arrays
Nline = new double [nmax];
NMline = new double [nmax][mmax];
The problem is, the 1D array is this way allocated. But the 2D array not - the compiler writes:
expression must have a constant value
Why the NLine was allocated and NMline not?
I understand but I don't know how to do it in my program and why for the 1D array this allocation is OK.
Many thanks for your help
double** NMline;
will declare pointer to array of pointers, it will not declare 2D array. You need to first allocate data for the array of pointers (pointers to rows):
NMline = new double*[nmax];
and then to initialize each row:
for(int i = 0; i < nmax; i++)
NMline[i] = new double[mmax];
Don't forget to first delete all rows, and then the NMline itself:
for(int i = 0; i < nmax; i++)
delete [] NMline[i];
delete [] NMline;