重复的可变参数模板参数

问题描述 投票:0回答:1

语境:

我是一名小型软件工程师,希望我不是重新发明轮子,请告诉我。我想创建一个模板函数,它包装并调用另一个函数元素。例如:

// returns a*x + y
__device__ float saxpy(float a, float x, float y) {
  return a*x + y;
}


int main() {
  int A[4] = { 1,2,3,4 };
  int X[4] = { 1,2,3,4 };
  int Y[4] = { 1,1,1,1 };

  // A*X   = 1,4,9,16
  // A*X+Y = 2,5,10,17
  float *C = cudaReduce(saxpy, A, X, Y);

  for (int i = 0; i < 4; i++)
    printf("%d, ", C[i]); // should print "2, 5, 10, 17, "

  std::cin.ignore();
  return 0;
}

重要的是,我想创建这个包装器,以便在执行元素操作时很好地包装cuda调用。虽然非常不完整,但这是我在函数包装器上的伪代码尝试。

我想提供一个最小的例子;但是,我对如何处理C ++的某些方面知之甚少,所以请原谅大量的注释伪代码:

#include "cuda_runtime.h"
#include "device_launch_parameters.h"

#include <iostream>

// returns a*x + y
__device__ float saxpy(float a, float x, float y) {
  return a*x + y;
}

// finds return type of function pointer
template<typename R, typename... A>
R ret(R(*)(A...));
template<typename C, typename R, typename... A>
R ret(R(C::*)(A...));

template<typename F, size_t N, typename... Args>
auto cudaReduce(F &f, Args(&...argsarray)[N]) {
  cudaSetDevice(0);

  // ret is function f's return type
  typedef decltype(ret(f)) ret;
  ret d_out[N], h_out[N];
  // cudaMalloc((void**)&d_out, sizeof(d_out));
  sendToCuda(argsarray...); // allocates and copies all contents of argsarray to cuda

  // reduceKernel<<<1, N>>>(f, d_out, dev_argsarray...);

  // cudaDeviceSynchronize();
  // cudaMemcpy(h_out, d_out, sizeof(h_out), cudaMemcpyDeviceToHost);
  // cudaFree(d_out);

  // for d_args in d_argsarray
  //   cudaFree(d_args);

  return h_out;
}

template<typename F, size_t N, typename Out, typename... Args>
__global__ void cudaReduceKernel(F &f, Out(&out)[N], Args(&...argsarray)[N]) {
  int tid = threadIdx.x;
  int i = tid + blockIdx.x * blockDim.x;

  // Below is invalid syntax; however, the 'pseudo-code' is what I'd like to achieve.
  // out[i] = f(argsarray[i]...);
}

// cuda malloc and memcpy
template<typename Arg, size_t N>
void sendToCuda(Arg(&args)[N]) {
  size_t buffer = sizeof(args);
  //cudaMalloc((void**)&dev_arg[ ??? ], buffer);
  //cudaMemcpy((void**)&dev_arg[ ??? ], args, buffer, cudaMemcpyHostToDevice);
}
template<typename Arg, size_t N, typename... Args>
void sendToCuda(Arg(&args)[N], Args(&...argsarray)[N]) {
  sendToCuda(args);
  sendToCuda(argsarray...);
}

int main() {
  int A[4] = { 1,2,3,4 };
  int X[4] = { 1,2,3,4 };
  int Y[4] = { 1,1,1,1 };

  // A*X   = 1,4,9,16
  // A*X+Y = 2,5,10,17
  float *C = cudaReduce(saxpy, A, X, Y);

  for (int i = 0; i < 4; i++)
    printf("%d, ", C[i]); // should print "2, 5, 10, 17, ", currently prints undefined behaviour

  std::cin.ignore();
  return 0;
}

我意识到不是每个人都有时间完全检查代码,所以我将把关键问题归结为几点:

1.是否可以复制可变参数模板输入,如果是这样的话? EX(不是真正的代码):

template<typename... Args>
void foo(Args... args) {
  Args... args2;
}

这是必要的,这样我就可以将输入参数复制到我的cuda malloc()memcpy()的输入参数中。

2.我将如何处理可变参数数组参数的第i个元组,例如在python中压缩。 EX(不是真正的代码):

template<typename... Args, size_t N>
void bar(Args(&...argsarray)[N]) {
  // (python) ithvariadic = zip(*argsarray)[i]
  auto ithvariadic = argsarray[i]...;
}
c++ c++11 templates cuda variadic-templates
1个回答
1
投票
  1. 是否可以复制可变参数模板输入,如果是这样的话? EX(不是真正的代码):
template <typename... Args>
 void foo(Args... args) {
  Args2... args;
 }

不是这样的。

Args...类型名是args...参数的免赔额。

但关于Args2...?你怎么能推断他们?你想要解释他们吗?

但你确定你需要不同的类型吗?

如果你不需要不同的类型列表,我可以想象的最好的,就像Jarod42所建议的那样,是使用一个元组

事情如下

template <typename ... Args>
void foo (Args ... args)  
 {
   std::tuple<Args...> tpl { args... };

   // do something with tpl`
 }

或者,如果你想启用完美转发,

template <typename ... Args>
void foo (Args && ... args)  
 {
   std::tuple<Args...> tpl { std::forward<Args>(args)... };

   // do something with tpl`
 }
  1. 我将如何处理可变参数数组参数的第i个元组,如在python中压缩。 EX(不是真正的代码):
template<typename... Args, size_t N>
void bar(Args(&...argsarray)[N]) {
  // (python) ithvariadic = zip(*argsarray)[i]
  auto ithvariadic = argsarray[i]...;
}

关于什么

template <typename ... Args, std::size_t N>
void bar (Args (&...argsarray)[N])
 {
   for ( auto ui = 0u ; ui < N ; ++ui )
    {
      std::tuple<Args...> ithvariadic { argsarray[ui]... };

      // do something with ithvariadic
    }
 }

?

© www.soinside.com 2019 - 2024. All rights reserved.