Skip to content
This repository has been archived by the owner on Mar 21, 2024. It is now read-only.

Consider always discarding __device__ lambdas' results #779

Closed
jaredhoberock opened this issue Apr 20, 2016 · 10 comments
Closed

Consider always discarding __device__ lambdas' results #779

jaredhoberock opened this issue Apr 20, 2016 · 10 comments
Assignees
Labels
thrust triage Needs investigation and classification. type: enhancement New feature or request.

Comments

@jaredhoberock
Copy link
Contributor

jaredhoberock commented Apr 20, 2016

Host functions can't rely on the result of std::result_of when it is instantiated with a __device__ lambda.

If we have the means to detect their presence at compile time, then one option is to entirely ban them from bulk_invoke and friends. A more relaxed policy might be to always interpret their result to be void. That would still allow them to be used, but it would not be possible to return results from them.

@jaredhoberock jaredhoberock added the type: enhancement New feature or request. label Apr 20, 2016
@brycelelbach
Copy link
Collaborator

I don't think there's a way to detect that it's a lambda.

I'm not sure I understand why result_of doesn't work in this instance?

Would decltype work?

@brycelelbach brycelelbach added the triage Needs investigation and classification. label Oct 13, 2017
@brycelelbach brycelelbach self-assigned this Oct 13, 2017
@jaredhoberock
Copy link
Contributor Author

The issue is that __device__ lambdas' always return int! Even if there is no return used inside at all. Ugh! That means utilities like result_of or invoke_result or decltype to can't reliably determine what __device__ lambdas return. :-(

Fortunately, we are able to distinguish __device__ lambdas from other types.

Agency uses this inside its implementation of result_of to treat all __device__ lambdas as if they return void.

@alliepiper
Copy link
Collaborator

I'm going to start using this issue to track the various "__device__ lambda aren't working" issues.

The issues Jared mentioned above are documented here in the current toolkit documentation.

Until we have a better system in place, users should stick with __host__ __device__ lambda or explicit __device__ functor objects instead.

@jrhemstad
Copy link
Collaborator

jrhemstad commented Oct 1, 2020

Just for completeness, the exact restriction is G.6.2p13:

As described above, the CUDA compiler replaces a device extended lambda defined in a host function with a placeholder type defined in namespace scope. This placeholder type does not define a operator() function equivalent to the original lambda declaration. An attempt to determine the return type or parameter types of the operator() function may therefore work incorrectly in host code, as the code processed by the host compiler will be semantically different than the input code processed by the CUDA compiler.

I've stopped using __device__ lambdas all together with Thrust after I learned about this restriction. Too great a chance of silent or non-obvious failures.

@harrism
Copy link
Contributor

harrism commented Oct 2, 2020

@jaredhoberock said "device lambdas always return int". That can't be true, I have used device lambdas that return non-int before. I guess what Jared means is that result_of on a device lambda always evaluates to int?

@alliepiper
Copy link
Collaborator

Correct. The device lambda object is replaced with a placeholder object in host code, and that placeholder's API does not accurately represent the device lambda's actual call signature.

@jrhemstad
Copy link
Collaborator

jrhemstad commented Oct 2, 2020

I guess what Jared means is that result_of on a device lambda always evaluates to int

https://godbolt.org/z/6ob7q5

Not necessarily, no. It's moreso that the return type of the callable (as determined from host code) cannot be relied upon to be correct.

@harrism
Copy link
Contributor

harrism commented Oct 2, 2020

I just wanted reassurance that if I call a device lambda that returns float from a kernel, it doesn't return int.

@pauleonix
Copy link

I'm going to start using this issue to track the various "__device__ lambda aren't working" issues.

#1650 (comment) has a reproducer for an issue with both __device__ and __host__ __device__ lambdas causing thrust::transform_output_iterator< ... >::operator= to be deleted. Further information in #1650 (comment)

@jrhemstad
Copy link
Collaborator

Thanks to NVIDIA/libcudacxx#284, we will automatically error at compile time in instances where we attempt to query the return type of an extended lambda in a context where that is not supported.

@github-project-automation github-project-automation bot moved this to Done in CCCL Mar 7, 2023
pauleonix added a commit to pauleonix/thrustshift that referenced this issue May 2, 2023
Use __host__ __device__ lambdas instead of pure __device__ lambdas to avoid problems with their return type.
See NVIDIA/thrust#779 (comment)
In CUDA 12 one could use cuda::proclaim_return_type from libcu++ instead, but this wont work for earlier CUDA versions.

Add -DCUDA_FORCE_CDP1_IF_SUPPORTED to allow the usage of legacy CUDA Dynamic Parallelism
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
thrust triage Needs investigation and classification. type: enhancement New feature or request.
Projects
Archived in project
Development

No branches or pull requests

6 participants