pass a 2D array from a C++ class to a CUDA function - c++

I am a Java guy jumping into CUDA and the syntax is tripping me. I'm trying to create a matrix in the .cpp file then pass that off to the .cu file to be processed. I see examples where the CUDA function expects the 2D array to come in looking like
void handleMatrix(float* A){
// do stuff
}
when I create the matrix I'm used to doing it in code that looks like this:
int main()
{
const int row=8;
const int column=8;
int rnum;
srand(time(0));
rnum = (rand() % 100) + 1;
float table[row][column];
for(int r=0; r<row; r++){
for(int c=0; c<column;c++){
table[row][column] = (rand()%100) + 1.f;
}
cout << "\n";
}
handleMatrix(table);
return 0;
}
When I compile the code I'm getting the error
cannot convert ‘float ()[8]’ to ‘float*’ for argument ‘1’ to ‘void handleMatrix(float*)’*
Is there a different way I should be declaring the matrix or creating it?
Thanks in advance for the help.

You can do
handleMatrix(table[0]);
or, equivalently,
handleMatrix(&table[0][0]);
That's if 'handleMatrix' is host code. If it's device code, you can't allocate the buffer like that. You'll want to assemble an array in local memory, fill the entries, allocate another array in the device memory using cudaMalloc() or cudaMallocPitch(), and then copy from local to device using cudaMemcpy() or cudaMemcpy2D().

You want a pointer to an array. The syntax for declaring a pointer to an array is
void handleMatrix(float (*A)[8][8]) {
// do stuff
}
That is, when you dereference A, you get a reference to an 8 by 8 array of floats.
Even for 1D arrays, there is a distinction between pointer to array (float (*anArray)[100]) and pointer to element (float *anArray). C++ will transparently convert the former to the latter, which means that for 1D arrays (but not arrays of higher dimension) you can usually ignore the difference.

In your example, table[0] converts to a valid float* pointer to 64 consecutive float numbers. But it looks highly suspicious that handleMatrix takes a pointer meant to be an array and doesn't take any information about the dimensions of that array.

the handleMatrix() function, is this a function from you or is part of a library? If the latter you may need to create the 2-d array as a long row x col 1-d array. If the former you need to change the function to accept a 2-d array e.g. handleMatrix(float**m) and pass the dimensions of the matrix to the function;
preferably though you should use vector<> when programming in C++ then the dimensions are known by the callee.
e.g.
#include <vector>
typedef std::vector<std::vector<float > > matrix;
void handleMatrix( matrix& m ) {..}

Related

Finding main diagonal matrix using pointer array

I'm new to c++,
I'm trying to find main diagonal matrix using pointer array like
int * ProblemSolution :: solution(int *A,int N)
{
//write your code here
for (int m=0;m<N;m++){
for (int x=0;x<N;x++){
if(m=x)
cout<<*(*(A+m)+x)<<",";
}
}
return 0;
}
but i'm getting some kind of error:
can anyone help me?
You have a few problems
if(m=x)
is an assignment, you probably want,
if(m==x)
Square bracket syntax is a lot clearer than pointer arithmetic,
A[m]
instead of,
*(A+m)
Also *(A+m) is an integer, so *(A+m)+x is also an integer which you can't dereference.
Your index should be something like:
A[m*N+x]
A is an int*
A+m is also an int*
*(A+m) is an int
(*(A+m) + x) is also an int
Instead of cout<<*(*(A+m)+x)<<","; you could write int tmp = (*(A+m)+x); cout << *tmp << ",";.
You are trying to derefence a pointer.
To make things easier you should rather use appropriate types (e.g. std::array, std::vector) instead of using raw-pointers.
*(*(A+m) + x) is an int,So try to store it in some variable then print it. Also you are mixing up 2D matrix(pointer to pointer) with 1D array(pointer).
try to do like-
*(A+m)=A[m] ,
*(*(A+m)+x) =A[m][x]
You mixed up 2D matrix represented by pointer to pointer and 1D array represented by pointer, your case is the latter.
*(*(A+m)+x) is legal only if A is a pointer to array decayed to a pointer to pointer, instead it should be *(A + N*m +x)

How to convert between flat and multidimensional arrays without copying data?

I've got some data structured as a multi-dimensional array, i.e. double[][], and I need to pass it to a function that expects a single linear array of double[] along with dimensional metadata for the multi-dimensional representation.
For example, I might have a 3 x 5 multidimensional array, which I need to pass as a 15-element flat array along with height and width parameters so that the function knows it is a 3x5 array rather than a 5x3 array.
The function will then return a flat array and size metadata, which I need to use to convert the data back into a multidimensional type.
I believe the data layout in memory is exactly the same for both the flat and multi-dimensional representations; the only difference is how the indexing operations are performed. So I'd like to do the "conversion" with typecasting rather than copying the array values.
What's the most correct and readable way to typecast between multidimensional and flat arrays of the same total size?
I actually know what the dimensions of the multi-dimensional array will be at compile time. The array sizes aren't dynamic.
The most correct way has been given by #Maxim Egorushkin and #ypnos: double *flat = &multi[0][0];. And it will work fine with any decent compiler. But unfortunately is not valid C++ code and invokes Undefined Bahaviour.
The problem is that for an array double multi[N][M]; (N and M being compile time contant expressions), &multi[0][0] is the address of the first element of an array of size M. So it is legal to do pointer arithmetics only up to M. See this other question of mine for more details.
What's the most correct and readable way to typecast between multidimensional and flat arrays of the same total size?
The address of the first array element coincides with the address of the array. You can pass around the address of the first element, no casting is necessary.
I would assume the most popular way to do it is:
double *flat = &multi[0][0];
This is how it is done in C, and you do operate with simple C arrays.
You could also have a look at std::array in your use case (dimensions known at compile time), but that one is not multi-dimensional, so if you would cascade it, you would lose the contiguous layout.
You can use cast to a reference to an array. This require to use some fancy C++ type syntax but in return it allows to use all features that work on arrays, like for each loop.
#include <iostream>
using namespace std;
int main()
{
static constexpr size_t x = 5, y = 3;
unsigned multiArray[x][y];
for (size_t i = 0; i != x; ++i)
for (size_t j = 0; j != y; ++j)
multiArray[i][j] = i * j;
static constexpr size_t z = x * y;
unsigned (&singleArray)[z] = (unsigned (&)[z])multiArray[0][0];
for (const unsigned value : singleArray)
cout << value << ' ';
cout << endl;
return 0;
}
Take into account that this and other methods basing on casts work only with real multi-dimensional arrays. If it is an array of arrays (like unsigned **multiArray;), it isn't allocated in a continuous block of memory and a cast cannot bypass that.

How to pass a two dimensional array to a function in c++

I am trying to pass an array (2d) to a function as an parameter.
I have a code as follows:
int main()
{
float T[100][100];
void set_T(float T[][]);
}
void set_T(float T1[][])
{
for (int i =0 ; i<90;i++)
{
for(int j =0 ;j <90;j++)
{
T1[i][j] = 3;
}
}
}
I am not sure how to pass array to a function ...I am getting lot of errors. Can any one help please.
There are two issues here:
C does not support 2D arrays, only arrays of arrays or arrays of pointers to arrays, neither of which is quite the same thing as a 2D array
C does not allow passing arrays to functions as arguments, only pointers into arrays (generaly, you use a pointer to an array's 0th element, since that's what the array's name ends up being so indexing off of such a pointer looks just like an array access)
So because of the first problem, you have to decide how you're going to represent a 2D array -- either an array of arrays, or an array of pointers to arrays. If you go the first route, your code ends up looking like:
void set_T(float (*T1)[100]) {
... do stuff with T1[i][j] ...
}
int main() {
float T[100][100];
set_T(T);
}
Here, you've declared T to be an array of 100 arrays of 100 floats, and set_T takes a pointer to arrays of 100 floats as its argument. You pass 'T' directly to set_T, as the language treats array names as pointers to their 0th element.
If instead you want to use an array of pointers to arrays, you end up with something like:
void set_T(float **T1) {
... do stuff with T1[i][j] ...
}
int main() {
float *T[100];
float space[100*100];
for (int i = 0; i < 100; i++)
T[i] = space + i*100;
set_T(T);
}
The disadvantage here is that you need to allocate space for all of the second-level arrays and manually initialize all the first-level pointers to point at them. The advangtage is that the sizes of the second level arrays is not part of the type of the argument passed to set_T, so you can more easily deal with variable-sized arrays.
Of course, if you're really using C++ and not C, you should not be using C arrays at all -- you should be using std::vector or std::array instead -- both of which share the C array 1D only issue, so you need a vector of vectors or an array of arrays (or conceivably a vector of arrays or an array of vectors)
void set_T(float (&T)[100][100]);
Just call it like this:
int main ()
{
float T[100][100];
set_T(T);
}
And as #suddnely_me said, the type of T1 in the function declaration need to be float**.

Passing array with unknown size to function

Let's say I have a function called MyFunction(int myArray[][]) that does some array manipulations.
If I write the parameter list like that, the compiler will complain that it needs to know the size of the array at compile time. Is there a way to rewrite the parameter list so that I can pass an array with any size to the function?
My array's size is defined by two static const ints in a class, but the compiler won't accept something like MyFunction(int myArray[Board::ROWS][Board::COLS]).
What if I could convert the array to a vector and then pass the vector to MyFunction? Is there a one-line conversion that I can use or do I have to do the conversion manually?
In C++ language, multidimensional array declarations must always include all sizes except possibly the first one. So, what you are trying to do is not possible. You cannot declare a parameter of built-in multidimensional array type without explicitly specifying the sizes.
If you need to pass a run-time sized multidimensional array to a function, you can forget about using built-in multidimensional array type. One possible workaround here is to use a "simulated" multidimensional array (1D array of pointers to other 1D arrays; or a plain 1D array that simulates multidimensional array through index recalculation).
In C++ use std::vector to model arrays unless you have a specific reason for using an array.
Example of a 3x2 vector filled with 0's called "myArray" being initialized:
vector< vector<int> > myArray(3, vector<int>(2,0));
Passing this construct around is trivial, and you don't need to screw around with passing length (because it keeps track):
void myFunction(vector< vector<int> > &myArray) {
for(size_t x = 0;x < myArray.length();++x){
for(size_t y = 0;y < myArray[x].length();++y){
cout << myArray[x][y] << " ";
}
cout << endl;
}
}
Alternatively you can iterate over it with iterators:
void myFunction(vector< vector<int> > &myArray) {
for(vector< vector<int> >::iterator x = myArray.begin();x != myArray.end();++x){
for(vector<int>::iterator y = x->begin();y != x->end();++y){
cout << *y << " ";
}
cout << endl;
}
}
In C++0x you can use the auto keyword to clean up the vector iterator solution:
void myFunction(vector< vector<int> > &myArray) {
for(auto x = myArray.begin();x != myArray.end();++x){
for(auto y = x->begin();y != x->end();++y){
cout << *y << " ";
}
cout << endl;
}
}
And in c++0x for_each becomes viable with lambdas
void myFunction(vector< vector<int> > &myArray) {
for_each(myArray.begin(), myArray.end(), [](const vector<int> &x){
for_each(x->begin(), x->end(), [](int value){
cout << value << " ";
});
cout << endl;
});
}
Or a range based for loop in c++0x:
void myFunction(vector< vector<int> > &myArray) {
for(auto x : myArray){
for(auto y : *x){
cout << *y << " ";
}
cout << endl;
}
}
*I am not near a compiler right now and have not tested these, please feel free to correct my examples.
If you know the size of the array at compile time you can do the following (assuming the size is [x][10]):
MyFunction(int myArray[][10])
If you need to pass in a variable length array (dynamically allocated or possibly just a function which needs to take different sizes of arrays) then you need to deal with pointers.
And as the comments to this answer state:
boost::multiarray may be appropriate since it more efficiently models a multidimensional array. A vector of vectors can have performance implications in critical path code, but in typical cases you will probably not notice an issue.
Pass it as a pointer, and take the dimension(s) as an argument.
void foo(int *array, int width, int height) {
// initialize xPos and yPos
assert(xPos >= 0 && xPos < width);
assert(yPos >= 0 && yPos < height);
int value = array[yPos * width + xPos];
}
This is assuming you have a simple two-dimensional array, like int x[50][50].
There are already a set of answers with the most of the common suggestions: using std::vector, implementing a matrix class, providing the size of the array in the function argument... I am only going to add yet another solution based on native arrays --note that if possible you should use a higher level abstraction.
At any rate:
template <std::size_t rows, std::size_t cols>
void function( int (&array)[rows][cols] )
{
// ...
}
This solution uses a reference to the array (note the & and the set of parenthesis around array) instead of using the pass-by-value syntax. This forces the compiler not to decay the array into a pointer. Then the two sizes (which could have been provided as compile time constants can be defined as template arguments and the compiler will deduct the sizes for you.
NOTE: You mention in the question that the sizes are actually static constants you should be able to use them in the function signature if you provide the value in the class declaration:
struct test {
static const int rows = 25;
static const int cols = 80;
};
void function( int *array[80], int rows ) {
// ...
}
Notice that in the signature I prefer to change the double dimension array for a pointer to an array. The reason is that this is what the compiler interprets either way, and this way it is clear that there is no guarantee that the caller of the function will pass an array of exactly 25 lines (the compiler will not enforce it), and it is thus apparent the need for the second integer argument where the caller passes the number of rows.
You can't pass an arbitrary size like that; the compiler doesn't know how to generate the pointer arithmetic. You could do something like:
MyFunction(int myArray[][N])
or you could do:
MyFunction(int *p, int M, int N)
but you'll have to take the address of the first element when you call it (i.e. MyFunction(&arr[0][0], M, N).
You can get round all of these problems in C++ by using a container class; std::vector would be a good place to start.
The compiler is complaining because it needs to know the size of the all but the first dimension to be able to address an element in the array. For instance, in the following code:
int array[M][N];
// ...
array[i][j] = 0;
To address the element, the compiler generates something like the following:
*(array+(i*N+j)) = 0;
Therefore, you need to re-write your signature like this:
MyFunction(int array[][N])
in which case you will be stuck with a fixed dimension, or go with a more general solution such as a (custom) dynamic 2D array class or a vector<vector<int> >.
Use a vector<vector<int> > (this would be cheating if underlying storage was not guaranteed to be contiguous).
Use a pointer to element-of-array (int*) and a size (M*N) parameter. Here be dragons.
First, lets see why compiler is complaining.
If an array is defined as int arr[ ROWS ][ COLS ]; then any array notation arr[ i ][ j ] can be translated to pointer notation as
*( arr + i * COLS + j )
Observe that the expression requires only COLS, it does not require ROWS. So, the array definition can be written equivalently as
int arr [][ COLS ];
But, missing the second dimension is not acceptable. For little more details, read here.
Now, on your question:
Is there a way to rewrite the
parameter list so that I can pass an
array with any size to the function?
Yes, perhaps you can use a pointer, e.g. MyFunction( int * arr );. But, think about it, how would MyFunction() know where to stop accessing the array? To solve that you would need another parameter for the length of the array, e.g. MyFunction( int * arr, size_t arrSize );
Yes: MyFunction(int **myArray);
Careful, though. You'd better know what you're doing. This will only accept an array of int pointers.
Since you're trying to pass an array of arrays, you'll need a constant expression as one of the dimentions:
MyFunction(int myArray[][COLS]);
You'll need to have COLS at compile time.
I suggest using a vector instead.
Pass a pointer and do the indexing yourself or use a Matrix class instead.
yes - just pass it as pointer(s):
MyFunction(int** someArray)
The downside is that you'll probably need to pas the array's lengths as well
Use MyFunction(int *myArray[])
If you use MyFunction(int **myArray) an pass int someArray[X][Y], the program will crash.
EDIT: Don't use the first line, it's explained in comments.
I don't know about C++, but the C99 standard introduced variable length arrays.
So this would work in a compiler that supports C99:
void func(int rows, int cols, double[rows][cols] matrix) {
for (int r = 0; r < rows; r++) {
for (int c = 0; c < cols; c++) {
printf("%f", matrix[r][c]);
}
}
}
Note that the size arguments come before the array. Really, only the number of columns has to be known at compile time, so this would be valid as well:
void func(int rows, int cols, double[][cols] matrix)
For three or more dimensions, all but the first dimension must have known sizes. The answer ArunSaha linked to explains why.
Honestly, I don't know whether C++ supports variable-length arrays, so this may or may not work. In either case, you may also consider encapsulating your array in some sort of matrix class.
EDIT: From your edit, it looks like C++ may not support this feature. A matrix class is probably the way to go. (Or std::vector if you don't mind that the memory may not be allocated contiguously.)
Don't pass an array, which is an implementation detail. Pass the Board
MyFunction(Board theBoard)
{
...
}
in reality my array's size is defined by two static const ints in a class, but the compiler won't accept something like MyFunction(int myArray[Board::ROWS][Board::COLS]).
That's strange, it works perfectly fine for me:
struct Board
{
static const int ROWS = 6;
static const int COLS = 7;
};
void MyFunction(int myArray[Board::ROWS][Board::COLS])
{
}
Maybe ROWS and COLS are private? Can you show us some code?
In C++, using the inbuilt array types is instant fail. You could use a boost::/std:: array of arrays or vector of arrays. Primitive arrays are not up to any sort of real use
In C++0x, you can use std::initializer_list<...> to accomplish this:
MyFunction(std::initializer_list<std::initializer_list<int>> myArray);
and use it (I presume) like this (with the range based for syntax):
for (const std::initializer_list<int> &subArray: myArray)
{
for (int value: subArray)
{
// fun with value!
}
}

C++ Inserting 2D array Object into another 2D array Object

In using Dev C++, I a m trying to insert a smaller 2D array object into a larger 2D array object. While attempting to achieve that, I came into compilers errors which I do not know how to solve.
I attempt to insert the smaller Object by making it returning the array's name. Then I attempt to change the values inside the large array with the values of the smaller array.
There two line of code that I have problems with:
int result = smallerArray.extractPiece();
largerArray.extractArray(result);
And within these two lines of codes:
int Piece::extractPiece()
{
return **pieceArray;
}
and
void Grid::extractArray( int** arr )
{
for(int i = 0; i &lt xGrid ; ++i)
{
for (int j = 0; j &lt yGrid ; ++j)
{
squares[i][j] = arr[i][j];
}
}
}
The two of the problems is that "int result" will not hold smallerArray.extractPiece(),
and if i just put "smallerArray.extractPiece()" in largerArray.extractArray(), i still get problems. I attempted to make "int result" a pointer pointer, as "int** result", i still have the same errors.
These are the errors that i get when i try to compile in Dev C++:
In function `int main()';
invalid conversion from `int' to `int**'
initlizing argument 1 of 'void Grid::extractArray(int**)'
[Build Error] [grid test.o] Error 1
Does anyone know whats wrong?
It's precisely this bunch of code:
int result = smallerArray.extractPiece();
largerArray.extractArray(result);
// ...
int Piece::extractPiece() {
return **pieceArray;
}
Trying to pass an int to extractArray, which wants a pointer to a pointer, presumable your dynamic array, and not an int. Try changing it to
int **result = smallerArray.extractPiece();
largerArray.extractArray(result);
// ...
int ** Piece::extractPiece() {
return pieceArray;
}
Only changing result to a pointer to pointer won't work. You of course also have to change what extractPiece returns (changing from int to int**)
Look, always at least for me it was easier to manage 2D arrays internally as 1D arrays where M[i,j]=A[i*N+j] where N is the number of cols (or rows, if the 2D arrays is row-column type). Users may get elements with the i,j indices but my class always store A[M * N] as private data. Passing 1-D pointer arrays is easier than managing 2-D pointer arrays (you can't fall in the pointer-to-pointer syntax which can get messy in some code).,
This is not related to this question, but since I don't know about specific compiler optimization instrinsics, I wonder if M[i,j] gets transformed to A[i] internally to use simpler addressing modes in the generated code.