Community
cancel
Showing results for 
Search instead for 
Did you mean: 
giltirn
Novice
165 Views

Error using trivially copy-constructible data member of a non-trivially constructible parent class

Jump to solution

For Intel(R) oneAPI DPC++/C++ Compiler 2021.2.0 (2021.x.0.20210323),  if one has a parent object that is not trivially copy-constructible, such as

std::pair<double, std::vector<double> > the_pair

then accessing the trivially copyable data member the_pair.first inside the kernel results in compile errors:

test.C:60:17: error: kernel parameter has non-trivially copy constructible class/struct type 'std::pair<double, std::vector<double>>'
data[i] = the_pair.first;

However adding an intermediate reference:

double &first_elem_ref = the_pair.first;

and accessing first_elem_ref inside the kernel is allowed. This suggests that the compiler is treating accesses to trivially copyable members by attempting to copy the entire object rather than just the member.

Attached is a simple demonstration. To use,

> make broken <-- error
> make working <--- no error

using the attached.

It seems to me that this should not be the intended behavior?

0 Kudos
1 Solution
giltirn
Novice
129 Views

Hi Rahul,

Thank you for your response. What I was trying to convey was that I believe the auto capture should only capture the actual data used in the kernel, in this case it should only copy the double "the_pair.first", but instead the compiler complains because it is trying to copy the entire object "the_pair" to the GPU, which contains a member which is not trivially copyable.

That being said, I have done a little research and it seems that the same behavior also applies for regular c++ lambdas, e.g.

struct my_struct{
  double a;
  my_struct() = default;
  my_struct(const my_struct &r) = delete;
};

template<typename T>
void lambda_apply(const T&l){
  l();
}

int main(void){
  my_struct d;
  d.a = 3.14;
  double test;
  double* test_p = &test;

  lambda_apply([=]{ *test_p = d.a; });

  return 0;
}

with g++ gives

test.cc:18:16: error: use of deleted function 'my_struct::my_struct(const my_struct&)'
18 | lambda_apply([=]{ *test_p = d.a; });
| ^~~~~~~~~~~~~~~~~~~~~
test.cc:4:3: note: declared here
4 | my_struct(const my_struct &r) = delete;
| ^~~~~~~~~
make: *** [Makefile:2: test] Error 1

Thus it seems that g++ also is trying to capture the entire object and not just the member. As such I will complain no further and will use the intermediate reference workaround if necessary.

Thanks,
Chris

 

 

View solution in original post

3 Replies
RahulV_intel
Moderator
137 Views

Hi,

 

>>This suggests that the compiler is treating accesses to trivially copyable members by attempting to copy the entire object rather than just the member.

 

Could you please let me know how did you arrive at this conclusion? 

 

Alternatively, since you only require the data of the first pair to be read-only, instead of creating a reference variable, you may store the data in a temporary variable and assign that variable to data[i].

 

 

  double first_elem = the_pair.first;
  accelerator_for(i, 100, 1, {
#ifdef USE_BROKEN
      data[i] = the_pair.first;
#else
      data[i] = first_elem;
#endif
    });

 

 

 

Let us know if you face any issues.

 

Thanks,

Rahul

giltirn
Novice
130 Views

Hi Rahul,

Thank you for your response. What I was trying to convey was that I believe the auto capture should only capture the actual data used in the kernel, in this case it should only copy the double "the_pair.first", but instead the compiler complains because it is trying to copy the entire object "the_pair" to the GPU, which contains a member which is not trivially copyable.

That being said, I have done a little research and it seems that the same behavior also applies for regular c++ lambdas, e.g.

struct my_struct{
  double a;
  my_struct() = default;
  my_struct(const my_struct &r) = delete;
};

template<typename T>
void lambda_apply(const T&l){
  l();
}

int main(void){
  my_struct d;
  d.a = 3.14;
  double test;
  double* test_p = &test;

  lambda_apply([=]{ *test_p = d.a; });

  return 0;
}

with g++ gives

test.cc:18:16: error: use of deleted function 'my_struct::my_struct(const my_struct&)'
18 | lambda_apply([=]{ *test_p = d.a; });
| ^~~~~~~~~~~~~~~~~~~~~
test.cc:4:3: note: declared here
4 | my_struct(const my_struct &r) = delete;
| ^~~~~~~~~
make: *** [Makefile:2: test] Error 1

Thus it seems that g++ also is trying to capture the entire object and not just the member. As such I will complain no further and will use the intermediate reference workaround if necessary.

Thanks,
Chris

 

 

View solution in original post

RahulV_intel
Moderator
89 Views

Hi,


Since your issue is resolved, I will go ahead and close this thread from my end. Intel will no longer monitor this thread. Further interactions on this thread will be considered community only.


Thanks,

Rahul


Reply