namespace tf {

/** @page ForEachCUDA Parallel Iterations 

tf::cudaFlow provides two template methods, tf::cudaFlow::for_each
and tf::cudaFlow::for_each_index, for creating tasks to perform
parallel iterations over a range of items.

@tableofcontents

@section CUDAForEachIncludeTheHeader Include the Header

You need to include the header file, `%taskflow/cuda/algorithm/for_each.hpp`, 
for creating a parallel-iteration task.

@code{.cpp}
#include <taskflow/cuda/algorithm/for_each.hpp>
@endcode

@section ForEachCUDAIndexBasedParallelFor Index-based Parallel Iterations

Index-based parallel-for performs parallel iterations over a range <tt>[first, last)</tt> with the given @c step size.
The task created by tf::cudaFlow::for_each_index(I first, I last, I step, C callable) 
represents a kernel of parallel execution
for the following loop:

@code{.cpp}
// positive step: first, first+step, first+2*step, ...
for(auto i=first; i<last; i+=step) {
  callable(i);
}
// negative step: first, first-step, first-2*step, ...
for(auto i=first; i>last; i+=step) {
  callable(i);
}
@endcode

Each iteration @c i is independent of each other and is assigned one kernel thread 
to run the callable.
Since the callable runs on GPU, it must be declared with a <tt>%__device__</tt> specifier.
The following example creates a kernel that assigns each entry of @c gpu_data 
to 1 over the range @c [0, 100) with step size 1.

@code{.cpp}
// assigns each element in gpu_data to 1 over the range [0, 100) with step size 1
cudaflow.for_each_index(0, 100, 1, [gpu_data] __device__ (int idx) {
  gpu_data[idx] = 1;
});
@endcode

@section ForEachCUDAIteratorBasedParallelIterations Iterator-based Parallel Iterations

Iterator-based parallel-for performs parallel iterations over a range specified 
by two STL-styled iterators, @c first and @c last.
The task created by tf::cudaFlow::for_each(I first, I last, C callable) represents 
a parallel execution of the following loop:

@code{.cpp}
for(auto i=first; i<last; i++) {
  callable(*i);
}
@endcode

The two iterators, @c first and @c last, are typically two raw pointers to the 
first element and the next to the last element in the range in GPU memory space.
The following example creates a @c for_each kernel that assigns each element in
@c gpu_data to 1 over the range <tt>[gpu_data, gpu_data + 1000)</tt>.

@code{.cpp}
// assigns each element to 1 over the range [gpu_data, gpu_data + 1000)
cudaflow.for_each(gpu_data, gpu_data + 1000, [] __device__ (int& item) {
  item = 1;
}); 
@endcode

Each iteration is independent of each other and is assigned one kernel thread 
to run the callable.
Since the callable runs on GPU, it must be declared with a <tt>%__device__</tt> specifier.

@section ForEachCUDAMiscellaneousItems Miscellaneous Items

The parallel-iteration algorithms are also available in 
tf::cudaFlowCapturer::for_each and tf::cudaFlowCapturer::for_each_index.

*/
}






