Intel® oneAPI DPC++/C++ Compiler
Talk to fellow users of Intel® oneAPI DPC++/C++ Compiler and companion tools like Intel® oneAPI DPC++ Library, Intel® DPC++ Compatibility Tool, and Intel® Distribution for GDB*
613 Discussions

About SYCL_EXTERNAL issue when separating defitions from declaration of a class

PC-1
Beginner
847 Views

I previously posted a similar question but not really get a solution. Suppose I need to call a function object and its member function in a kernel:

____________________

Q.submit([&](sycl::handler& h) {

sycl::accessor A(B, h);
h.parallel_for(size, [=](auto& idx) {
my_class& mc_ref =A[idx];
mc_ref.update();      //call member function of my_class
}
);
});

________

According to SYCL specifications, I need to define "my_class" and corresponding member function "my_class::update()" in one header, like

in "my_class.h"_____________

class my_class{

.....

void update()  { .... ;  return; }

.....

};

________________

Hoever,  if I separate definition from class declaration, like

in "my_class.h"_____________

class my_class{

.....

void update() ;

.....

};

in "my_class.cpp"_____________

void my_class::update() { ... ; return;}

___________________________

It would generate compiler error : SYCL kernel cannot call an undefined function without SYCL_EXTERNAL attribute, since the member function is now defined under a different translation unit.

 

My question is that if there is anyway, or how can I declare "SYCL_EXTERNAL" in this situation so that I can separate class definiton from declaration ??

 

I need to do this because my code is a little compilcated, and in "my_class" there would be another class objects. (I usually manage data and abstration by C++ class).

If I put all defitions of member functions in one header file, it would be more than 5k lines... which I think is a little crazy and hard to read.

 

Could anyone provide me an example or some suggestions on how to organize my program in this case? 

Thanks so much!

 

 

 

 

 

 

 

 

 

 

__________

0 Kudos
1 Solution
RabiyaSK_Intel
Employee
795 Views

Hi,

 

Thanks for posting in Intel Communities.

 

>>My question is that if there is anyway, or how can I declare "SYCL_EXTERNAL" in this situation so that I can separate class definiton from declaration ??

 

Yes, you can provide function declaration in a class and it's definition in another file but as per SYCL specifications, the function will come under different translation unit. Please make sure to include "SYCL_EXTERNAL" before function declaration in your header file.

 

Please go through the modified code files to understand it better.

main.cpp

#include "my_class1.h"

int main()
{
size_t N = 4;

sycl::buffer<int> B(N);
{
sycl::host_accessor a(B, sycl::write_only);
for (int i = 0; i < N; i++) {
a[i] = i;
}
}

queue Q;
Q.submit([&](sycl::handler& h) {
sycl::accessor A(B, h);
h.parallel_for(N, [=](item<1> i) {
my_class mc_ref;
mc_ref.update(A, i);      //call member function of my_class
});
});

host_accessor h{B};
for(int i=0;i<N;i++)
std::cout<<h[i]<<" ";
return 0;
}

my_class.cpp

#include "my_class1.h"


//Methods
void my_class::update(cl::sycl::accessor<int, 1, cl::sycl::access::mode::read_write> A, cl::sycl::item<1> i)
{
	int idx=i.get_id();
	A[idx]=A[idx]+1;
}

my_class1.h

#pragma once
#include<iostream>
#include<CL/sycl.hpp>
using namespace sycl;

class my_class{

public:

//extern 
SYCL_EXTERNAL void update(cl::sycl::accessor<int, 1, cl::sycl::access::mode::read_write> A, cl::sycl::item<1> i);
};

Hope this resolves your issue, if you still face any issues please share the sample reproducer code with us.

 

Thanks & regards,

Shaik Rabiya

 

View solution in original post

3 Replies
RabiyaSK_Intel
Employee
796 Views

Hi,

 

Thanks for posting in Intel Communities.

 

>>My question is that if there is anyway, or how can I declare "SYCL_EXTERNAL" in this situation so that I can separate class definiton from declaration ??

 

Yes, you can provide function declaration in a class and it's definition in another file but as per SYCL specifications, the function will come under different translation unit. Please make sure to include "SYCL_EXTERNAL" before function declaration in your header file.

 

Please go through the modified code files to understand it better.

main.cpp

#include "my_class1.h"

int main()
{
size_t N = 4;

sycl::buffer<int> B(N);
{
sycl::host_accessor a(B, sycl::write_only);
for (int i = 0; i < N; i++) {
a[i] = i;
}
}

queue Q;
Q.submit([&](sycl::handler& h) {
sycl::accessor A(B, h);
h.parallel_for(N, [=](item<1> i) {
my_class mc_ref;
mc_ref.update(A, i);      //call member function of my_class
});
});

host_accessor h{B};
for(int i=0;i<N;i++)
std::cout<<h[i]<<" ";
return 0;
}

my_class.cpp

#include "my_class1.h"


//Methods
void my_class::update(cl::sycl::accessor<int, 1, cl::sycl::access::mode::read_write> A, cl::sycl::item<1> i)
{
	int idx=i.get_id();
	A[idx]=A[idx]+1;
}

my_class1.h

#pragma once
#include<iostream>
#include<CL/sycl.hpp>
using namespace sycl;

class my_class{

public:

//extern 
SYCL_EXTERNAL void update(cl::sycl::accessor<int, 1, cl::sycl::access::mode::read_write> A, cl::sycl::item<1> i);
};

Hope this resolves your issue, if you still face any issues please share the sample reproducer code with us.

 

Thanks & regards,

Shaik Rabiya

 

PC-1
Beginner
762 Views

Thanks so much, Shaik!

I tried your code and it works.

The reason I got stuck here is because I always think "extern" can only be used for a variable or a function, instead of a class member function....

I know that my question is very fundamental and is probably not worth for you spending time to provide an answer : )

 

Anyway, really thanks!

 

Best regards,

 

PC

 

 

 

0 Kudos
RabiyaSK_Intel
Employee
744 Views

Hi,


Thanks for accepting our solution. If you need any additional information, please post a new question as this thread will no longer be monitored by Intel. 


Thanks & Regards,

Shaik Rabiya


0 Kudos
Reply