I have a large code that I need to pass a struct to a CUDA kernel that has a larger number of ints for parameters and a vector. I can't figure out how to pass the struct to the CUDA kernel. I've copied it to the device, but get the following error when trying to compile:
test_gpu.cpp:63:17: error: invalid operands to binary expression ('void (*)(Test)' and 'dim3')
computeTotal<<dimGrid, dimBlock>>(test_Device);
test_gpu.cpp:63:36: error: invalid operands to binary expression ('dim3' and 'Test *')
computeTotal<<dimGrid, dimBlock>>(test_Device);
Attached is a small almost working example of the code, any ideas?
#include <stdio.h>
#include <stdlib.h>
#include <cuda_runtime_api.h>
#include <cuda.h>
#include <cuda_runtime.h>
#include <device_functions.h>
#include <device_launch_parameters.h>
#include <vector>
#include <string>
typedef struct Test{
int x;
int y;
int z;
std::vector<int> vector;
std::string string;
}Test;
Test test;
__device__ void addvector(Test test, int i){
test.x += test.vector[i];
test.y += test.vector[i+1];
test.z += test.vector[i+2];
}
__global__ void computeTotal(Test test){
for (int tID = threadIdx.x; tID < threadIdx.x; ++tID )
addvector(test, tID);
}
int main()
{
Test test_Host;
int vector_size = 512;
test_Host.x = test_Host.y = test_Host.z = 0;
for (int i=0; i < vector_size; ++i)
{
test_Host.vector.push_back(rand());
}
Test* test_Device;
int size = sizeof(test_Host);
cudaMalloc((void**)&test_Device, size);
cudaMemcpy(test_Device, &test_Host, size, cudaMemcpyHostToDevice);
dim3 dimBlock(16);
dim3 dimGrid(1);
computeTotal<<dimGrid, dimBlock>>(test_Device);
return 0;
}
Items from C++ standard libraries aren't generally/normally usable in CUDA device code. The documentation support for this is here.
For this particular case, it means you may have trouble with either std::vector or std::string. One possible workaround is to replace these with ordinary C-style arrays:
#define MAX_VEC_SIZE 512
#define MAX_STR_SIZE 512
typedef struct Test{
int x;
int y;
int z;
int vec[MAX_VEC_SIZE];
char str[MAX_STR_SIZE];
}Test;
This will of course necessitate changes elsewhere in your code.
Related
Im trying to use the power of function pointers, it all went fine until i tried to make the function pointer use a 2nd argument as type int.
The code below generates an error, which is displayed below
In an header file:
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct UnitTag {
int x;
int y;
void (*move)(Unit, int);
} Unit;
Error:
error: expected ‘)’ before ‘int’
void (*move)(Unit, int);
^
void (*move)(Unit); works all fine, which surprises me how adding an argument can cause an error.
I call my struct in a C file, by including header and then doing:
Unit units[UNITCOUNT];
units[0].move(&units[0], 1);
Update:
adding:
typedef struct UnitTag Unit
Causes the error to dissapear, however I can no longer use the function as before.
error: incompatible type for argument 1 of ‘units[i].move’
units[0].move(&units[0], 0);
^
note: expected ‘Unit’ but argument is of type ‘struct UnitTag *’
If I'm getting you, you can simply use struct keyword:
#include <stdio.h>
typedef struct UnitTag {
int x;
int y;
void (*move)(struct UnitTag, int);
} Unit;
void Test (struct UnitTag test1, int test2)
{
printf("Test1.x: %d\n", test1.x);
printf("Test1.y: %d\n", test1.y);
printf("Test2 : %d\n", test2);
}
int main(void)
{
Unit units[100];
units[0].move = Test;
units[0].x = 1;
units[0].y = 2;
units[0].move(units[0], 3);
}
Output:
Test1.x: 1
Test1.y: 2
Test2 : 3
If you want to pass struct by referebce, simply:
#include <stdio.h>
typedef struct UnitTag {
int x;
int y;
void (*move)(struct UnitTag*, int);
} Unit;
void Test (struct UnitTag *test1, int test2)
{
test1->x = 4;
test1->y = 5;
}
int main(void)
{
Unit units[100];
units[0].move = Test;
units[0].x = 1;
units[0].y = 2;
units[0].move(&units[0], 3);
printf("units[0].x: %d\n", units[0].x);
printf("units[0].y: %d\n", units[0].y);
}
Output is:
units[0].x: 4
units[0].y: 5
You need the prototype for Unit before using it.
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct UnitTag Unit;
typedef struct UnitTag {
int x;
int y;
void (*move)(Unit, int);
} Unit;
int main(void)
{
return 0;
}
After the clarification what you wanted to do. It probably makes more sense to give a pointer to Unit, so that the move command which returns void can change something about your object.
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct UnitTag Unit;
typedef struct UnitTag {
int x;
int y;
void (*move)(Unit *, int);
} Unit;
Unit test;
/* some function that corresponds to the interface */
void myMove(Unit *u, int i)
{
u->x = u->x + i;
}
int main(void)
{
/* initialize test struct */
test.x = 0;
test.y = 0;
test.move = myMove;
test.move(&test, 5);
printf("Values after move are (x, y) = (%i, %i).\n", test.x, test.y);
return 0;
}
I am trying to declare a struct and use it in multiple files and I am getting an error that I cannot figure out. Sample code is posted below.
in test.h
#ifndef TEST_H
#define TEST_H
struct mystruct;
struct mystruct *new_mystruct();
void myprint(struct mystruct*,int);
#endif
int test.c
#include "test.h"
#include <stdio.h>
#include <stdlib.h>
struct mystruct {
int *myarray;
};
struct mystruct *new_mystruct(int length)
{
int i;
struct mystruct *s;
s = malloc(sizeof(struct mystruct));
s->myarray = malloc(length*sizeof(int));
for(i = 0; i < length; ++i)
s->myarray = 2*i;
return s;
}
in main.c
#include "test.h"
#include <stdio.h>
int main()
{
int len = 10;
struct mystruct *c = new_mystruct(len);
myprint(c, len);
printf("%f", c->myarray[3]); // error: dereferencing pointer to incomplete type
return 0;
myprint() prints out 0 2 4 6 8 10 12 14 16 18. why doesn't the myprint(function work but the printf statement doesn't? why is it ok to pass it into a function but not use it in main? Thanks.
Currently main() only knows that struct mystruct is a type, but it doesn't know anything about its internal structure, because you've hidden it in test.c.
So you need to move this definition:
struct mystruct {
int *myarray;
};
from test.c to test.h, so that it's visible to main().
Note: what you're doing here is a classic example of an opaque type. This can be a very useful technique when you want to hide implementation details from code that is going to be calling your API.
Main.c doesn't know the contents of the mystruct structure. Try moving these lines:
struct mystruct {
int *myarray;
};
from test.c to test.h.
While you're at it, I think you mean "int myarray" not "int *myarray".
I'm fully prepared to be told that I'm doing something stupid/wrong; this is what I expect.
I'm getting a feel for structures and coming a cropper when it comes to accessing the fields from the pointers. Code to follow.
matrix.h:
#ifndef MATRIX_H_INCLUDED
#define MATRIX_H_INCLUDED
#include <stdlib.h>
typedef struct
{
size_t size;
int* vector;
} vector_t;
#endif // MATRIX_H_INCLUDED
main.c:
#include <stdio.h>
#include <stdlib.h>
#include "matrix.h"
vector_t* vector_new(size_t size)
{
int vector[size];
vector_t v;
v.size = size;
v.vector = vector;
return &v;
}
int main(int argc, char* argv[])
{
vector_t* vec = vector_new(3);
printf("v has size %d.\n", vec->size);
printf("v has size %d.\n", vec->size);
return EXIT_SUCCESS;
}
So this is a very simple program where I create a vector structure of size 3, return the pointer to the structure and then print its size. This, on the first print instance is 3 which then changes to 2686668 on the next print. What is going on?
Thanks in advance.
You are returning a pointer to a local variable v from vector_new. This does not have a slightest chance to work. By the time vector_new returns to main, all local variables are destroyed and your pointer points to nowhere. Moreover, the memory v.vector points to is also a local array vector. It is also destroyed when vector_new returns.
This is why you see garbage printed by your printf.
Your code has to be completely redesigned with regard to memory management. The actual array has to be allocated dynamically, using malloc. The vector_t object itself might be allocated dynamically or might be declared as a local variable in main and passed to vector_new for initialization. (Which approach you want to follow is up to you).
For example, if we decide to do everything using dynamic allocation, then it might look as follows
vector_t* vector_new(size_t size)
{
vector_t* v = malloc(sizeof *v);
v->size = size;
v->vector = malloc(v->size * sizeof *v->vector);
return v;
}
(and don't forget to check that malloc succeeded).
However, everything that we allocated dynamically we have to deallocate later using free. So, you will have to write a vector_free function for that purpose.
Complete re-write of answer to address your question, and to provide alternate approach:
The code as written in OP will not compile: &v is an illegal return value.
If I modify your code as such:
#include <stdlib.h>
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
size_t size;
int* vector;
} vector_t;
vector_t* vector_new(size_t size)
{
int vector[size];
vector_t v, *pV;
pV = &v;
pV->size = size;
pV->vector = vector;
return pV;
}
int main(int argc, char* argv[])
{
vector_t* vec = vector_new(3);
printf("v has size %d.\n", vec->size);
printf("v has size %d.\n", vec->size);
getchar();
return EXIT_SUCCESS;
}
It builds and runs, but returns unintended values for vec->size in main() due to the local scope of that variable in the function vector_new.
Recommend creating globally visible instance of your struct, and redefine vector_new() to int initVector(void):
#include <stdlib.h>
#include <stdio.h>
#include <stdlib.h>
#define SIZE 10
typedef struct
{
size_t size;
int* vector;
} vector_t;
vector_t v, *pV;//globally visible instance of struct
int initVector(void)
{
int i;
pV->size = SIZE;
pV->vector = calloc(SIZE, sizeof(int));
if(!pV->vector) return -1;
for(i=0;i<SIZE;i++)
{
pV->vector[i] = i;
}
return 0;
}
int main(int argc, char* argv[])
{
int i;
pV = &v; //initialize instance of struct
if(initVector() == 0)
{
printf("pV->size has size %d.\n", pV->size);
for(i=0;i<SIZE;i++) printf("pV->vector[%d] == %d.\n", i, pV->vector[i]);
}
getchar(); //to pause execution
return EXIT_SUCCESS;
}
Yields these results:
You still need to write a freeVector function to undo all the allocated memory.
I have such a code
#include <dlfcn.h>
#include <stdlib.h>
#include "timer.h"
#define SIZE 9000
void *memorylib;
void *arraylib;
typedef struct {
int rows;
int columns;
long **d;
} array;
int main(){
memorylib = dlopen("libmemory.so", RTLD_LAZY);
if(!memorylib){
exit(-1);
}
arraylib = dlopen("libarray.so",RTLD_LAZY);
if(!arraylib) {
exit(-1);
}
typedef void (*memory_initialize)(long);
typedef void * (*memory_add)(long);
typedef array *(*memory_allocate)(int,int);
memory_add add = (memory_add) dlsym(memorylib,"add");
memory_initialize initialize = (memory_initialize) dlsym(memorylib, "initialize");
memory_allocate allocate = (memory_allocate) dlsym(arraylib,"allocate");
initialize(SIZE*sizeof(int)/1024 + 1);
int rows = 10;
int columns = 10;
array *m = allocate(rows,columns);
dlclose(memorylib);
dlclose(arraylib);
return 0;
}
and initialize method works, but when I try to use allocate method I get an error
symbol lookup error: /usr/local/lib/libarray.so: undefined symbol: add
I use this add method in my allocate method which comes from memory.h
#include <stdio.h>
#include <stdlib.h>
#include "array.h"
#include "memory.h"
array * allocate(int rows, int columns) {
// printf("%i",sizeof(array));
array *m = (array *) add(sizeof(array));
m->rows = rows;
m->columns = columns;
int i;
long **d = (long**)add(rows* sizeof(long*));
for(i=0;i< rows;i++) {
d[i] = (long *) add(columns * sizeof(long));
}
m->d = d;
return m;
}
How to fix it ? It's probably fail, because I don't load library dynamically to file containing allocate method ?
You need to use the flag RTLD_GLOBAL when loading libmemory.so so that symbols in it will be available for use by subsequently loaded libraries (such as libarray.so). By default, symbols in a library are only visible to that library and to dlsym calls using that library.
I am trying to create a function which allocates memory for a structure array defined in "main". The problem seems to be that my function does not recognize the structure. What is wrong with the following code?
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
typedef struct typecomplex { float r; float i; } complex;
complex *myfunction(int n);
int main (int argc, char *argv[]) {
complex *result = myfunction(1000);
exit(0);
}
... and in another file...
struct complex *myfunction(int n) {
complex *result = (complex *)malloc(n*sizeof(*complex));
if(result==NULL) return(NULL);
else return(result);
}
Building on fvdalcin's answer:
myprog.c:
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include "mycomplex.h"
int main (int argc, char *argv[]) {
complex *result = myfunction(1000);
exit(0);
}
mycomplex.h:
#ifndef __MYCOMPLEX_H__
typedef struct typecomplex { float r; float i; } complex;
complex *myfunction(int n);
#define __MYCOMPLEX_H__
#endif
(The #ifdef's are a good idea to keep it from being included more than once.)
mycomplex.c:
#include <stdlib.h>
#include "mycomplex.h"
complex *myfunction(int n) {
complex *result = malloc(n*sizeof(complex));
if(result==NULL) return(NULL);
else return(result);
}
Note subtle but important fixes here--sizeof(complex) instead of sizeof(complex*), declaration of myfunction() doesn't include the keyword "struct", and no cast on malloc()--it doesn't need one and can hide the fact that you may be missing the include file with its prototype (see Do I cast the result of malloc?). myfunction() could actually by simplified down to one line:
return malloc(n*sizeof(complex));
Move this declaration typedef struct _complex { float r; float i; } complex; to the "other" file. This other file has to be your foo.h file, which has an foo.c equivalent which implements the methods declared in the foo.h. Then you can simply add the foo.h to your main.c file and everything will work fine.
Here is a code with corrections that compiles well:
typedef struct typecomplex { float r; float i; } complex;
complex *myfunction(int n) {
complex *result = (complex *)malloc(n*sizeof(complex)); //removed * from sizeof(*complex)
if(result==NULL) return(NULL);
else return(result);
}
int main (int argc, char *argv[]) {
complex *result = myfunction(1000);
exit(0);
}