cuda header files - cuda

I have a file named "KernelUtil.cu" as follows
__device__ int add(int a, int b)
{
return a+b;
}
I have my main program which is "main.cu". I need to call the "add" function from here. How can I do it?? The following doesnt work.
#include "KernelUtil.cu"
__global__ void test()
{
int c = add(10,10);
}
int main()
{
test<<<1,1>>>();
}
giving an error add is already defined in main.cu

I expect that you have a rule that automatically compiles all .cu files, meaning KernelUtil.cu is effectively compiled twice, once on its own and once when included in main.cu, and therefore add is duplicated.
Try renaming KernelUtil.cu to KernelUtil.h (or .cuh).

Related

nvcc warns about a device variable being a host variable - why?

I've been reading in the CUDA Programming Guide about template functions and is something like this working?
#include <cstdio>
/* host struct */
template <typename T>
struct Test {
T *val;
int size;
};
/* struct device */
template <typename T>
__device__ Test<T> *d_test;
/* test function */
template <typename T>
T __device__ testfunc() {
return *d_test<T>->val;
}
/* test kernel */
__global__ void kernel() {
printf("funcout = %g \n", testfunc<float>());
}
I get the correct result but a warning:
"warning: a host variable "d_test [with T=T]" cannot be directly read in a device function" ?
Has the struct in the testfunction to be instantiated with *d_test<float>->val ?
KR,
Iggi
Unfortunately, the CUDA compiler seems to generally have some issues with variable templates. If you look at the assembly, you'll see that everything works just fine. The compiler clearly does instantiate the variable template and allocates a corresponding device object.
.global .align 8 .u64 _Z6d_testIfE;
The generated code uses this object just like it's supposed to
ld.global.u64 %rd3, [_Z6d_testIfE];
I'd consider this warning a compiler bug. Note that I cannot reproduce the issue with CUDA 10 here, so this issue has most likely been fixed by now. Consider updating your compiler…
#MichaelKenzel is correct.
This is almost certainly an nvcc bug - which I have now filed (you might need an account to access that.
Also note I've been able to reproduce the issue with less code:
template <typename T>
struct foo { int val; };
template <typename T>
__device__ foo<T> *x;
template <typename T>
int __device__ f() { return x<T>->val; }
__global__ void kernel() { int y = f<float>(); }
and have a look at the result on GodBolt as well.

passing structure to a file in c

I've seen some answers on StackOverflow regarding this. In my c project, I am using the main function and a child function. The child function is written in a separate .c file, with its header file included in the main file.
#include<stdio.h>
struct student
{
int t1;
float e1;
};
typedef struct student stu;
#include"struct_demo.h"
void main()
{
stu s1;
stu *r1=&s1;
s1.t1=10;
s1.e1=172.1;
struct_demo(r1);
}
And the function struct_demo.c is as follows
#include"stdio.h"
void struct_demo(stu *s1)
{
s1->e1=9;
printf("%d",s1->e1);
}
The header file for the function struct_demo is
#ifndef STRUCT_DEMO_H_
#define STRUCT_DEMO_H_
void struct_demo(stu *s1);
#endif /* STRUCT_DEMO_H_ */
My compiler is showing errors in the child function
expression must have pointer-to-struct-or-union type
identifier stu is undefined
The same program when executed without the use of separate .c files (with functions written in a single .c file under separate function) works. Where am I going wrong?
struct student
{
int t1;
float e1;
};
typedef struct student stu;
Move this code struct_demo.h since the struct_demo.h doesn't know what is stu
for parsing the address you need to do
myStructure* myFunction(structure* myStructure)
{
//some opperation
return myStructure;
}
this way you are parsing the address of that structure but be careful when initializing it you will have to use calloc to make room in memory for it because at this point that pointer can go anywhere.

why the output of this program comes only by using extern ? Why not without it?

#include<stdio.h>
int main ()
{
printf("%d\n",z);
return 0;
}
int z=25;
why is output to this code is showing an error ?
The order in which you declare your functions/variables count in C. In your code, when the compiler parses your code, it encounters the symbol z, which has not yet been declared.
So, you need to put your int z = ... before the first time you use z, hence before main.
The extern keyword tells the compiler that the variable has been declared in another file, so it will be resolved during linking, i.e. when all the files are assembled into a program. So for the compilation of this file, the unresolved symbol z can be ignored => no compilation error.
Try this :
#include<stdio.h>
int z=25;
int main ()
{
printf("%d\n",z);
return 0;
}

SWIG parser error

I have following header file.
#include <string>
namespace A {
namespace B {
struct Msg {
std::string id;
std::string msg;
Msg(std::string new_id, std::string new_msg)
: id(new_id), msg(new_msg)
{
}
};
template<bool HAS_ID>
class ID {
public:
template<typename TOBJ>
auto get(TOBJ parent) -> decltype(parent.id()) {
return parent.id();
}
};
} // namespace B
} // namespace A
When i swig it, it gives me an error
Error: Syntax error in input(3). at line 20 pointing to line
auto get(TOBJ parent) -> decltype(parent.id())
Target language is Java
How can i fix this problem? I only want to create wrapper for Msg struct and for nothing else in the header. As this looks like a Swig parser error, using %ignore directive does not seem to work.
Thank you
Although SWIG 3.x added limited decltype support it looks like the case you have is unsupported currently. (See decltype limitations)
I think the best you'll get for now is to surround the offending code in preprocessor macros to hide it, e.g.:
#include <string>
namespace A {
namespace B {
struct Msg {
std::string id;
std::string msg;
Msg(std::string new_id, std::string new_msg)
: id(new_id), msg(new_msg)
{
}
};
template<bool HAS_ID>
class ID {
public:
#ifndef SWIG
template<typename TOBJ>
auto get(TOBJ parent) -> decltype(parent.id()) {
return parent.id();
}
#endif
};
} // namespace B
} // namespace A
If you can't edit the file like that for whatever reason there are two options:
Don't use %include with the header file that doesn't parse. Instead write something like:
%{
#include "header.h" // Not parsed by SWIG here though
%}
namespace A {
namespace B {
struct Msg {
std::string id;
std::string msg;
Msg(std::string new_id, std::string new_msg)
: id(new_id), msg(new_msg)
{
}
};
} // namespace B
} // namespace A
in your .i file, which simply tells SWIG about the type you want to wrap and glosses over the one that doesn't work.
Alternatively get creative with the pre-processor and find a way to hide it using a bodge, inside your .i file you could write something like:
#define auto // \
void ignore_me();
%ignore ignore_me;
Another similar bodge would be to hide the contents of decltype with:
#define decltype(x) void*
Which just tells SWIG to assume all decltype usage is a void pointer. (Needs SWIG 3.x and could be combined with %ignore which ought to do the ignore, or a typemap to really fix it)

C++: Explicit DLL Loading: First-chance Exception on non "extern C" functions

I am having trouble importing my C++ functions. If I declare them as C functions I can successfully import them. When explicit loading, if any of the functions are missing the extern as C decoration I get a the following exception:
First-chance exception at 0x00000000 in cpp.exe: 0xC0000005: Access violation.
DLL.h:
extern "C" __declspec(dllimport) int addC(int a, int b);
__declspec(dllimport) int addCpp(int a, int b);
DLL.cpp:
#include "DLL.h"
int addC(int a, int b) {
return a + b;
}
int addCpp(int a, int b) {
return a + b;
}
main.cpp:
#include "..DLL/DLL.h"
#include <stdio.h>
#include <windows.h>
int main() {
int a = 2;
int b = 1;
typedef int (*PFNaddC)(int,int);
typedef int (*PFNaddCpp)(int,int);
HMODULE hDLL = LoadLibrary(TEXT("../Debug/DLL.dll"));
if (hDLL != NULL)
{
PFNaddC pfnAddC = (PFNaddC)GetProcAddress(hDLL, "addC");
PFNaddCpp pfnAddCpp = (PFNaddCpp)GetProcAddress(hDLL, "addCpp");
printf("a=%d, b=%d\n", a,b);
printf("pfnAddC: %d\n", pfnAddC(a,b));
printf("pfnAddCpp: %d\n", pfnAddCpp(a,b)); //EXCEPTION ON THIS LINE
}
getchar();
return 0;
}
How can I import c++ functions for dynamic loading? I have found that the following code works with implicit loading by referencing the *.lib, but I would like to learn about dynamic loading.
Thank you to all in advance.
Update:
bindump /exports
1 00011109 ?addCpp##YAHHH#Z = #ILT+260(?addCpp##YAHHH#Z)
2 00011136 addC = #ILT+305(_addC)
Solution:
Create a conversion struct as
found here
Take a look at the
file exports and copy explicitly the
c++ mangle naming convention.
PFNaddCpp pfnAddCpp = (PFNaddCpp)GetProcAddress(hDLL, "?addCpp##YAHHH#Z");
Inevitably, the access violation on the null pointer is because GetProcAddress() returns null on error.
The problem is that C++ names are mangled by the compiler to accommodate a variety of C++ features (namespaces, classes, and overloading, among other things). So, your function addCpp() is not really named addCpp() in the resulting library. When you declare the function with extern "C", you give up overloading and the option of putting the function in a namespace, but in return you get a function whose name is not mangled, and which you can call from C code (which doesn't know anything about name mangling.)
One option to get around this is to export the functions using a .def file to rename the exported functions. There's an article, Explicitly Linking to Classes in DLLs, that describes what is necessary to do this.
It's possible to just wrap a whole header file in extern "C" as follows. Then you don't need to worry about forgetting an extern "C" on one of your declarations.
#ifdef __cplusplus
extern "C" {
#endif
__declspec(dllimport) int addC(int a, int b);
__declspec(dllimport) int addCpp(int a, int b);
#ifdef __cplusplus
} /* extern "C" */
#endif
You can still use all of the C++ features that you're used to in the function bodies -- these functions are still C++ functions -- they just have restrictions on the prototypes to make them compatible with C code.