 #include <agency/experimental/view.hpp>
 
 
-template<class View>
-void saxpy(agency::cuda::multidevice_executor& exec, size_t n, float a, View x, View y, View z)
+template<class Executor, class View>
+void saxpy(Executor& exec, size_t n, float a, View x, View y, View z)
 {
   using namespace agency;
 

}


template<class Container>
void time_saxpy()
{
  using namespace agency;
  using namespace agency::experimental;

  cuda::multidevice_executor exec;

  size_t n = 32 << 20;
  Container x(n, 1.f), y(n, 2.f), z(n);


  double seconds = elapsed.count() / num_trials;
  double gigabytes = double(3 * n * sizeof(float)) / (1 << 30);
  return gigabytes / seconds;
}


int main()
{
  // the right choice of container can make a huge difference to performance

  // a contiguous container such as std::vector is laid out in a single contiguous allocation
  using contiguous_container = std::vector<float, agency::cuda::managed_allocator<float>>;

  // a segmented container such as multidevice_array is pieced together from separate, contiguous allocations
  using segmented_container  = agency::cuda::experimental::multidevice_array<float>;

  // let's first measure the performance of SAXPY on a single GPU using a contiguous container
  using gpu_executor = agency::cuda::grid_executor;

  std::cout << "Measuring the performance of gpu SAXPY using contiguous containers..." << std::endl;
  auto singlegpu_bandwidth = time_saxpy<contiguous_container, gpu_executor>();
  std::cout << "SAXPY Bandwidth: " << singlegpu_bandwidth << " GB/s" << std::endl;

  std::cout << std::endl;

  // now let's use multiple gpus at once to execute SAXPY and see how the choice of container impacts performance
  using multigpu_executor = agency::cuda::multidevice_executor;

  std::cout << "Measuring the performance of multigpu SAXPY using contiguous containers..." << std::endl;
  auto multigpu_contiguous_bandwidth = time_saxpy<contiguous_container, multigpu_executor>();
  std::cout << "SAXPY Bandwidth: " << multigpu_contiguous_bandwidth << " GB/s" << std::endl;

  std::cout << std::endl;

  std::cout << "Measuring the performance of multigpu SAXPY using segmented containers..." << std::endl;
  auto multigpu_segmented_bandwidth = time_saxpy<segmented_container, multigpu_executor>();
  std::cout << "SAXPY Bandwidth: " << multigpu_segmented_bandwidth << " GB/s" << std::endl;

  std::cout << std::endl;

  std::cout << "Multigpu speedup: " <<  multigpu_segmented_bandwidth / singlegpu_bandwidth << "x" << std::endl;

  return 0;
}
