两个几乎相同的调用,一个有效,一个失败

发布于 2024-09-29 09:13:31 字数 1590 浏览 3 评论 0原文

我有这些模板函数,可以在带有 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”的实例与参数列表匹配

 参数类型为:(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***/
}

I have these template functions for use inline on device with 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);};

In the code I have

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

for int arrays x,y,and z. I get the error:

error: no instance of function template "cmax" matches the argument list

      argument types are: (int, int)

I get the error for cmax but not cmin. If I replace the cmax line with

#define cmax(a,b) ((a)>(b))?(a):(b)

that works just fine, but I don't want #defines, they are problematic. What the heck is going on here?

EDIT:
here is the full calling function. times is 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***/
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

ゞ记忆︶ㄣ 2024-10-06 09:13:31
Iy += cmax(0,imin-imax);

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

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

is not legal. You can't bind the literal 0 to an int& reference (but you can to a const int& reference).

居里长安 2024-10-06 09:13:31

如果xz是一个const数组,它们的元素类型将为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 有权回答。

If either x or z is a const array, their element type will be const int, which is not convertible to int&.

Try with:

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);
}

If T is always a primitive type like int, you can even pass the parameters by value:

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);
}

EDIT: @aschepler has the right answer.

冷︶言冷语的世界 2024-10-06 09:13:31

如果您的函数也采用引用作为参数,则在返回引用时应小心。您可能会返回对临时对象的引用!就像这样:

cmin(0,imin-imax);

这对于 int 和 float 来说可能没问题,但对于非 POD 来说是危险的。

You should be careful in returning a reference, if your functions also take references as arguments. You might return a reference to a temporary! Like in:

cmin(0,imin-imax);

which is probably ok for int and float, but dangerous for non-PODs.

提笔书几行 2024-10-06 09:13:31

请尝试颠倒定义顺序。

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 然后 cmmin。那么输出是什么?

Try to reverse the definition order please.

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 then cmin. What is the outpout then ?

风蛊 2024-10-06 09:13:31

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

很难说,因为示例不完整。

Your cmax and cmin are taking non-const reference to the elements. Maybe your arrays are declared as const?

Hard to tell, because the example is not complete.

晨曦慕雪 2024-10-06 09:13:31

也许您已经有一些活动的定义,它们会污染您的命名空间?尝试重命名cmincmax,或#undef cmin和#undef cmax。或者运行g++ -E来查看去宏化的代码。

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

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

无论如何,你只需要define中的所有()即可。更好:

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

而且您可能也不需要模板函数的内联。

Maybe you already have some active defines which pollute you namespace?Try renaming cmin and cmax, or #undef cmin and #undef cmax. Or run g++ -E to see the de-macrofied code.

Or add :: namespace specifier:

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

Anyway, you only need all the () in defines. Nicer:

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

And you probably do not need the inline for a template function neither.

青衫负雪 2024-10-06 09:13:31

为了澄清我对第一个问题的评论:是的,如果 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

在某些机器上,我猜它甚至可能段错误。在 Thing 的析构函数中,我将 data 重置为 0,但人们很容易想象更多。

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

To clarify my comment on the initial question: Yes, one should be careful if ona just passes through a reference from a parameter. Here is a complete illustration:

#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;
}

followed by

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;
}

The output is:

$ ./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

On some machines it might even segfault, I guess. In Things destructor I reset data to 0, but one could easily imagine more there.

So, when we do the BAD refmin call, we return a reference to a temporary. Which is destroyed after the ;. So, when we try to output &x, it's already gone.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文