两个几乎相同的呼叫,一个工作一个失败

时间:2010-10-29 17:41:40

标签: c++ templates cuda

我有这些模板函数可以在设备上使用cuda进行内联

template <class T> __device__ inline T& cmin(T&a,T&b){return (a<b)?(a):(b);};
template <class T> __device__ inline T& cmax(T&a,T&b){return (a>b)?(a):(b);};

在我的代码中

cmin(z[i],y[j])-cmax(x[i],z[j])

表示int数组x,y和z。我收到错误:

  

错误:没有函数模板“cmax”的实例与参数列表匹配

      argument types are: (int, int)

我得到cmax但不是cmin的错误。如果我用

替换cmax行
#define cmax(a,b) ((a)>(b))?(a):(b)

工作正常,但我不想#defines,它们是有问题的。到底发生了什么事?

编辑: 这是完整的调用功能。 times是typedef int。

__global__ void compute_integral_y_isums(times * admit, times * discharge, times * Mx, times * isums, ar_size N){
    // computes the sums for each j
    // blocks on j,
    // threads on i since we will be summing over i.
    // sumation over J should be handled by either a different kernel or on the cpu.
    ar_index tid = threadIdx.x;
    ar_index i = blockIdx.x;                       // summing for patient i 
    ar_index j = threadIdx.x; // across other patients j
    __shared__ times cache[threadsPerBlock];

  times Iy = 0;
    while(j<N){
        // R code:  max(0,min(Mx[i],d3[j,'Discharge.time'])-max(d3[i,'Admission.time'],Mx[j]))
        times imin = cmin(Mx[i],discharge[j]);
        times imax = cmax(admit[i],Mx[j]);
        Iy += cmax(0,imin-imax);
        j += blockDim.x;
    }
    cache[tid] = Iy;

    __syncthreads(); 
    // reduce 
    /***REMOVED***/
}

7 个答案:

答案 0 :(得分:7)

Iy += cmax(0,imin-imax);

不合法。您无法将文字0绑定到int&引用(但您可以const int&引用)。

答案 1 :(得分:4)

如果xzconst数组,则其元素类型将为const int,但不能转换为int&

尝试:

template<class T> __device__ inline T cmin(const T& a, const T& b)
{
    return (a < b ? a : b);
}

template<class T> __device__ inline T cmax(const T& a, const T& b)
{
    return (a > b ? a : b);
}

如果T始终是int等基本类型,您甚至可以按值传递参数:

template<class T> __device__ inline T cmin(T a, T b)
{
    return (a < b ? a : b);
}

template<class T> __device__ inline T cmax(T a, T b)
{
    return (a > b ? a : b);
}

编辑: @aschepler有正确答案。

答案 2 :(得分:1)

如果您的函数将引用作为参数,则应该小心返回引用。您可能会返回对临时的引用!喜欢在:

cmin(0,imin-imax);

对于intfloat来说可能没问题,但对于非POD则很危险。

答案 3 :(得分:0)

请尝试颠倒定义顺序。

template <class T> __device__ inline T& cmax(T&a,T&b){return (a>b)?(a):(b);};
template <class T> __device__ inline T& cmin(T&a,T&b){return (a<b)?(a):(b);};

cmax然后是cmin。什么是输出?

答案 4 :(得分:0)

你的cmax和cmin正在对元素进行非const引用。也许你的数组被声明为const?

很难说,因为这个例子并不完整。

答案 5 :(得分:0)

也许您已经有一些活跃的defines污染了您的名称空间?请尝试重命名cmincmax,或#undef cmin#undef cmax。或者运行g++ -E以查看解密码代码。

或添加::命名空间说明符:

::cmin(z[i],y[j])-::cmax(x[i],z[j])

无论如何,您只需要定义中的所有()。更好:

template  __device__ T& cmin(const T&a,const T&b){return a<b?a:b;};

您可能也不需要inline作为模板函数。

答案 6 :(得分:0)

在初始问题上澄清我的评论:是的,如果ona只是通过参数的引用,应该小心。以下是完整的说明:

#include <iostream>

struct Thing {
    int data;
    Thing() { data = 42; }
    Thing(int val) { data = val; }
    Thing(const Thing& oth) { data = oth.data; }
    Thing& operator=(const Thing& oth)
      { if(this!=&oth) this->data = oth.data; return *this; }
    ~Thing() { data = 0; } // clear, destroy, release...
};

bool operator<(const Thing &a, const  Thing &b) { return a.data 
const T& refmin(const T &a, const T &b) // return a ref
{
    return a < b ? a : b;
}


template
const T copymin(const T &a, const T &b) // return a copy
{
    return a < b ? a : b;
}

接着是

int main(int argc, const char* [])
{
    Thing a(11);
    Thing b(88);

    std::cerr << "Simple operation:" << std::endl;
    const Thing c = a + b;
    std::cerr << "  c:" << c.data << "  should be 99" << std::endl;

    std::cerr << "Working on temp expression (BAD):" << std::endl;
    const Thing &x = refmin(c, b-a); // '&x' will be gone after ';' 
    // the next line might crash:
    std::cerr << "  x:" << x.data << "  should be 77" << std::endl;

    std::cerr << "Working explicit side variable (OK):" << std::endl;
    const Thing &d = b-a;
    const Thing &y = refmin(c, d);  // '&y' is now same as '&d'
    std::cerr << "  d:" << d.data << "  should be 77" << std::endl;
    std::cerr << "  y:" << y.data << "  should be 77" << std::endl;

    std::cerr << "Working on a copy (OK):" << std::endl;
    const Thing &z = copymin(c, b-a);
    std::cerr <<  z:" << z.data << "  should be 77" << std::endl;

    return 0;
}

输出结果为:

$ ./minreftest
Simple operation:
  c:99  should be 99
Working on temp expression (BAD):
  x:0  should be 77
Working explicit side variable (OK):
  d:77  should be 77
  y:77  should be 77
Working on a copy (OK):
  z:77  should be 77

在某些机器上,我猜它甚至可能 segfault 。在Thing s析构函数中,我将data重置为0,但可以轻松想象更多内容。

因此,当我们执行 BAD refmin调用时,我们会返回对临时的引用。哪个在;之后被销毁。因此,当我们尝试输出&x时,它已经消失了。