views:

144

answers:

6

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***/
}
A: 

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 ?

yves Baumes
A: 

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.

VJo
If the type is const, T will be deduced as a const type. "T -(-42) is positive!)
Roger Pate
VJo
A: 
towi
You can incorporate more into a single answer, no need to post multiples.
Roger Pate
+4  A: 

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.

Frédéric Hamidi
it must be x that is constant because z is used in the call to cmin
Moe
Jon Purdy
@Moe, From the questioner's code sample, neither are `const` unless `times` is `typedefed` to `const int`, but then they would both be `const`. And the compiler would have to swap the calls to `cmax()` and `cmin()` *before* its semantic analysis, which I don't think it's allowed to do. I'm stumped.
Frédéric Hamidi
@Jon, seeing things like `cmin(a, b) = c;` in C++ still makes my skin crawl after all those years. I'd rather not do that :)
Frédéric Hamidi
This answered it. Correct @Frédéric Hamidi there is no const business here, but the things that solved it was the passing by value. apparently cuda does not like pass by ref.
Andrew Redd
If the type is const, T will be deduced as a const type. @Halpo: This is not the correct reason, even though it gave code that fixed the problem.
Roger Pate
+1  A: 

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.

towi
If you're returning a reference to the parameter, you're guaranteed it will be available until the end of the full-expression containing the function call. That's not the problem here.
Roger Pate
Yes, sure. But I was thinking about `T print(x);` (*boom*). If I see a *return-reference* I of course consider catching it *by reference*.
towi
Roger Pate
+5  A: 
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).

aschepler