I'm writing this simple cuda code and I'm unable to compile it. The code contains part of code written in C. This is the structure of the program:
read_data.c file contains a function called read_data
add.cu file contains a function called add (this is the part that should run in the GPGPU)
optimize.h file contains the necessary headers.
master.c file contains the main function.
The optimize.h file looks like follows:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <ctype.h>
#include <time.h>
__global__ void add(int, float*, float*);
void read_data(char*, float**, float**, int**);
master.c file looks like follows:
#include "optimize.h"
int main(){
char* path = "./data/0";
float* base_load;
float* comfortable_temperatures;
int* comfort_index;
read_data(path, &base_load, &comfortable_temperatures, &comfort_index);
int N = 1<<20;
float *x, *y;
int i;
cudaMallocManaged(&x, N*sizeof(float));
cudaMallocManaged(&y, N*sizeof(float));
for (i = 0; i < N; i++) {
x[i] = 1.0f;
y[i] = 2.0f;
}
add<<<1, 256>>>(N, x, y);
cudaDeviceSynchronize();
// still need to read the result back.
cudaFree(x);
cudaFree(y);
}
I compiled this using the following line:
nvcc -o master master.c read_data.c add.cu
and I'm getting this error:
In file included from master.c:1:0:
optimize.h:9:12: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘void’
__global__ void add(int, float*, float*);
^
master.c: In function ‘main’:
master.c:51:26: error: ‘add’ undeclared (first use in this function)
add<<<1, 256>>>(N, x, y);
^
master.c:51:26: note: each undeclared identifier is reported only once for each function it appears in
master.c:51:31: error: expected expression before ‘<’ token
add<<<1, 256>>>(N, x, y);
I think the whatever the error is, it should be a very small one. But I cannot find it.
nvcc by default treats filenames ending in .c or .cpp as having no CUDA-specific syntax, and sends those to the host compiler. The host compiler cannot handle CUDA-specific syntax, which is why you are getting the errors.
The usual recommendations are to place your CUDA code in files ending with .cu. You can alternatively pass -x cu as a compile switch to do this.
Note that nvcc uses c++ style linkage, so you will need to arrange for correct c-style linkage if you are trying to link code in a .cu file with code in a .c file. If you have no C-specific usage, again, a simple solution may be to rename your .c file to .cpp or .cu.
There are many questions here on the cuda tag explaining how to do C++/C linkage, otherwise.
Related
I am getting a really weird issue with my code.
I tried using clang and gcc, both tell me the same thing
init_twiddle.c:12:10: warning: implicitly declaring library function 'cosf' with type 'float (float)' [-Wimplicit-function-declaration]
.re = cosf(primitive_root*i) ,
^
init_twiddle.c:12:10: note: include the header <math.h> or explicitly provide a declaration for 'cosf'
init_twiddle.c:13:10: warning: implicitly declaring library function 'sinf' with type 'float (float)' [-Wimplicit-function-declaration]
.im = sinf(primitive_root*i)
^
init_twiddle.c:13:10: note: include the header <math.h> or explicitly provide a declaration for 'sinf'
2 warnings generated.
The code:
// file: init_twiddle.c
#include "complex.h"
#include <math.h>
void init_twiddle1024(Complex__complex* twiddle) {
int i,span ;
// Init the twiddles
for(span=1;span<=512;span<<=1) {
float primitive_root = -Complex__pi/span ;
for(i=0;i<span;i++) {
Complex__complex t =
{
.re = cosf(primitive_root*i) ,
.im = sinf(primitive_root*i)
} ;
twiddle[span+i] = t ;
}
}
}
// file: complex.h
#ifndef COMPLEX_H
#define COMPLEX_H
#include "stdbool.h"
#include "assert.h"
//#include "pervasives.h"
typedef struct Complex__complex {
float re;
float im;
} Complex__complex;
static const float Complex__pi = 3.141593;
#endif // COMPLEX_H
The command I use to compile:
gcc -I. -I$(heptc -where)/c/ -std=c99 -c init_twiddle.c
I am working on a project with some strange programming language which explain all the included directories.
Does someone have any idea of why I am getting those errors?
PS: note that it's not a linker issue but an issue at compile time.
It also does not seem to appear when I manually write the content of complex.h into the file
It turned out Barmar was right. I was including a directory where a math.h already exists, thus leading to not including the libc one.
The faulty one was -I$(heptc -where)/c/ for those who would have the same issue with the Heptagon langage.
Thanks for your help.
As commented by #Barmar, the issue is that in $(heptc -where)/c/ there is already a math.h header defined which don't implement the function you want to use in this exemple.
Considering it's to compile with Heptagon I would advise to copy the only file that is really useful in this case from $(heptc -where)/c/ which is pervasives.h where you have your init_twiddle.c and since you are compiling with -I. it will then compile perfectly fine.
I have a project that includes three files in codeblocks:
main.c :
#include <stdio.h>
#include <conio.h>
int global = 10;
void f1(int);
void f1_1(int);
void f2(void);
int main()
{
int x = 5;
printf("inside main file");
getch();
f1(x);
f2();
getch();
return 0;
}
file1.c :
#include <stdio.h>
#include <conio.h>
void f1(int x)
{
printf("\ninside file1 >> f1 and x = %i", x);
getch();
f1_1(x);
}
void f1_1(int x)
{
printf("\ninside file1 >> f1 >> f1_1 and x = %i", x);
getch();
}
file2.c :
#include <stdio.h>
#include <conio.h>
extern int global;
void f2()
{
printf("\ninside file2 >> f2 function , global var = %i", global);
getch();
}
When I compiled it, I got these warnings:
c|8|warning: implicit declaration of function 'f1_1'; did you mean 'f1'? [-Wimplicit-function-declaration]
c|11|warning: conflicting types for 'f1_1'
What should I do for this?
void f1(int);
void f1_1(int);
void f2(void);
Should be:
extern void f1(int);
extern void f1_1(int);
extern void f2(void);
Or, as #kiranBiradar points out, you can declare them in header files
file1.h
#pragma once
extern void f1(int);
extern void f1_1(int);
file2.h
#pragma once
extern void f2(void);
Note the use of the extern keyword. When you forward declare a function in a file as void f(void), the symbol 'f' is public, meaning other compilation units can reference it. When you declare it as extern void f(void), then the compiler doesn't expect the function to be defined in that compilation unit and leaves it up to the linker to find that symbol.
This is the perfect time to learn about the important concept of translation units.
Each single source file, with all included header file, forms a single translation unit. Each translation unit is separate and distinct and compiled stand-alone without any knowledge of other translation units.
That means symbols declared in e.g. the main.c source file will not be known in the file1.c source file.
When you compile file1.c the compiler simply doesn't know about the f1_1 function declaration you have in the main.c source file, so you get a warning about that fact.
To solve your problem, you need to declare the f1_1 function in the file1.c file. Either by adding a forward declaration (like the one you have in main.c), or moving the whole function definition (implementation) of f1_1 above the f1 function.
Or you could create a single header file which contains all the declarations needed (for the f1, f1_1, f2 function, plus the global external variable declaration), and include this single header file in all your source files. This solution works best if you have multiple symbols (functions, variables, etc.) that are used in multiple translation units.
My personal recommendation is this: Since the f1_1 function is only used internally inside the file1.c source file, move its definition above f1, and make it static. Then remove its declaration from the main.c source file.
Regarding the "implicit declaration" and "conflicting types" warnings, it's because in older standards of C it was allowed to not declare functions and the compiler would create an implicit declaration by guessing the declaration based on the first call of the function.
The important part about the guessing is that only the arguments were guessed, the return type would always be int.
I don't know the exact wording in the specifications about this since it was removed in the C99 specification, but most compilers still allow this with only emitting a warning instead of an error. This is where the first warning comes from.
However, the return type of int is still being used. And since your f1_1 function is declared to return void later in the file1.c source file, there's a mismatch between the guessed declaration (int f1_1(int)) and the actual declaration (void f1_1(int)) which leads to the second warning.
This is a header file
#include <stdio.h>
int m = 18;
int x = 4;
int singles (n) {
if (n == 1)
return 0;
return doubles(n-1);
}
int doubles (n) {
if (n == 1)
return 0;
return triples(n-1);
}
int triples (n) {
if (n == 1)
return m;
return (singles(n-1) + doubles (n-1) + triples (n-1))*(m-1);
}
and this is the main file
#include <stdio.h>
#include "test.h"
int main () {
printf("%d",singles (x));
}
So this is pretty complicated for me at-least.The idea is that in the main function i will call singles(x) where x =4 so its more like singles (4),it will call doubles (3),that will call triples (2),that will call all of singles(1) which will return 0,doubles (1) that returns 0 and triples (1) that will return m.
So the error i am getting is
./test.h:13:12: warning: implicit declaration of function 'doubles' is invalid
in C99 [-Wimplicit-function-declaration]
return doubles(n-1);
^
./test.h:20:12: warning: implicit declaration of function 'triples' is invalid
in C99 [-Wimplicit-function-declaration]
return triples(n-1);
^
2 warnings generated.
I tried to create a header file .h with the first script and then made a second .c script that i try to compile that won't work.I tried importing the header to try to avoid this error but it doesn't seem to work.
Thanks a lot
Inside of singles, you're using doubles before it's defined. Similarly in doubles, you're using triples before it's defined. That's why you're getting the implicit declaration errors.
Also, you're not defining the type of the n parameter to any of these functions.
You need to specify function prototypes, which declare the function without defining it:
int singles(int n);
int doubles(int n);
int triples(int n);
Also, you shouldn't define functions in a header file. If you include this header in multiple .c files and then link them together, you'll get an error because you'll have multiple definitions of those functions.
Take all of the function definitions and put them in test.c. Then in test.h, put only the prototypes above. Then you can compile everything as follows:
gcc -c test.c
gcc -c main.c
gcc -o main main.o test.o
Or in a single line:
gcc -o main test.c main.c
The term "implicit declaration" in an error message is usually generated when the compiler sees the implementation of a call to a function before the declaration (prototype).
For example, you should have:
header file
int singles(int x);
int doubles(int x);
int triples(int x);
In your source file:
#include "header_file.h"
Also, in your function definitions (implementations) you need to specify the type of the argument:
int singles (/* data type */ parameter_name)
{
//...
}
Edit 1: Changed implementation to function call per #John Bollinger.
In my prototype file, proto.h, I have
#define LOOP_LIMIT 90.00
#define PI 3.14159
#ifndef _PROTO_H
#define _PROTO_H
#include <stdio.h>
#include <math.h>
#include "get_problem.c"
#include "deg_to_rad.c"
#include "evaluate_sin.c"
#include "evaluate_cos.c"
#include "evaluate_tan.c"
int main(void);
int get_problem();
double deg_to_rad(int deg);
void evaluate_sin(int deg);
void evaluate_cos(int deg);
void evaluate_tan(int deg);
#endif
In my lab7.c I have my main function and I include proto.h. When I try to compile on Linux using the "make" command, I get the following message:
gcc -c deg_to_rad.c deg_to_rad.c: In function ‘deg_to_rad’:
deg_to_rad.c:2: error: ‘PI’ undeclared (first use in this function)
deg_to_rad.c:2: error: (Each undeclared identifier is reported only once
deg_to_rad.c:2: error: for each function it appears in.)
make: * [deg_to_rad.o] Error 1
I really don't understand this because my main function uses LOOP_LIMIT correctly, but PI isn't working.
deg_to_rad.c:
double deg_to_rad(int deg) {
double rad = (PI * deg) / 180;
return rad;
}
#include "get_problem.c"
#include "deg_to_rad.c"
#include "evaluate_sin.c"
#include "evaluate_cos.c"
#include "evaluate_tan.c"
NO NO, You shouldn't be including C files!!!
In general, You declare functions in header(.h) files, define them in source files(.c) and include the header files in source files(.c) wherever you need to use the functions.
Also, show the definition of deg_to_rad() function, the compiler clearly tells you the problem lies there, I suspect you try to call one of the other functions in the function.
The compiler rightly complains because the functions are declared after the point where you include the source file.
You need to follow the general practice of header and source files mentioned above.
I have a script that compiles fine on Linux (Ubuntu 11.04), but not on OS X (Lion).
gcc -pthread -o hw1 hw1.c
hw1.c:22: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘barr’
hw1.c: In function ‘__syncthreads’:
hw1.c:53: error: ‘barr’ undeclared (first use in this function)
hw1.c:53: error: (Each undeclared identifier is reported only once
hw1.c:53: error: for each function it appears in.)
hw1.c:54: error: ‘PTHREAD_BARRIER_SERIAL_THREAD’ undeclared (first use in this function)
hw1.c: In function ‘parallel_psum’:
hw1.c:94: error: ‘barr’ undeclared (first use in this function)
hw1.c:107: warning: assignment from incompatible pointer type
Here's the first 22 lines of the code:
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <math.h>
#include <sys/time.h>
#include <pthread.h>
#include <assert.h>
/* create thread argument struct for thr_func() */
typedef struct _thread_data_t {
int tid;
int* ints;
int* sums;
int num_ints;
int* temp;
} thread_data_t;
const int MIN_RAND_INT = 1;
const int MAX_RAND_INT = 65000;
// pthreads barrier variable
pthread_barrier_t barr;
Any ideas why this is happening?
According to info about pthread_barriers on opengroup.org, barriers are defined in the optional part of POSIX standard; the name of option is "(ADVANCED REALTIME THREADS)", sometimes more exact referred as "BAR, barriers (real-time)".
http://pubs.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap02.html
The system may support one or more options (see Options) denoted by the following symbolic constants:
_POSIX_BARRIERS
So, only if the _POSIX_BARRIERS macro is defined as positive number, you can use pthread_barrier_t or pthread_barrier_wait.
Mac OS X is POSIX Compliant, but full list of implemented options is not available online. There is a letter in apple mainling list from 2006, which says there is no barriers in Mac OS X.
I know that Solaris had some problems with pthread_barrier too.
Just like osgx mentioned, barriers are not implemented on OS X, but you can always implement it or just use this implementation. Quick note on the previous implementation, you can use the macro that osgx mentioned, _POSIX_BARRIERS, instead of the ones on the blog, like this #if !defined _POSIX_BARRIERS || _POSIX_BARRIERS < 0