stuhlo
stuhlo

Reputation: 1507

Altering if-statement condition in consideration of template argument

I have a global kernel function with template argument:

template<int ARG> __global__ void kernel(array[]) {
    int threadID = blockDim.x*blockIdx.x + threadIdx.x;
    if(...) {...}
}

The behaviour of the function, and a specially if-statement condition, is slightly varying in consideration of template argument but the body stays the same. Lets say:
ARG == 0 if statement looks like: if(expr1){body}
ARG == 1 if statement looks like: if(expr2){body}
ARG == 2 if statement looks like: if(expr1 && expr2){body}

My question is what is the best way(in a sense of readability and performance) to provide this?

EDIT: Expressions expr1 and expr2 are calls to __device__ boolean functions, e.g. fnc1(array[threadID]) and fnc2(array[threadID]).

Upvotes: 1

Views: 425

Answers (3)

Drew Dormann
Drew Dormann

Reputation: 63946

ARG == 0 if statement looks like: if(expr1){body}

ARG == 1 if statement looks like: if(expr2){body}

ARG == 2 if statement looks like: if(expr1 && expr2){body}

Code that directly, since that's your own interpretation of readable.

It will be performant since ARG can be resolved at compile time.

if ( ARG == 0 && expr1 ) {body}

if ( ARG == 1 && expr2) {body}

if ( ARG == 2 && expr1 && expr2 ) {body}

Or, if {body} is heavy, combine them.

if ( ARG == 0 && expr1 ) ||

   ( ARG == 1 && expr2) ||

   ( ARG == 2 && expr1 && expr2 ) {body}

Upvotes: 0

shakurov
shakurov

Reputation: 2518

You can declare an auxiliary class template:

template<int ARG>
class IfCondition {
};

and specialize it for different values of ARG:

template<>
class IfCondition<0> {
public:
    static bool Get() {
        return expr1;
    }
};

template<>
class IfCondition<1> {
public:
    static bool Get() {
        return expr2;
    }
};

template<>
class IfCondition<2> {
public:
    static bool Get() {
        return expr1 && expr2;
    }
};

Then use it inside your template like this:

if (IfCondition<ARG>::Get())
     ...

}

The nice thing about it is that, with inlining, it'll be as fast as literally writing if(expr1) {body} or if (expr2) {body} or whatnot.

EDIT

Another way to go is with template function specialization:

template<int ARG>
bool ifCondition() { return false; }

template<>
bool ifCondition<0>() { return expr1; }

template<>
bool ifCondition<1>() { return expr2; }

template<>
bool ifCondition<2>() { return expr1 && expr2; }

// Then later, inside your template:
if (ifCondition<ARG>()) {
    ...
}

Upvotes: 1

Pete Becker
Pete Becker

Reputation: 76498

The straightforward approach is brute force:

if ((ARG != 1 || expr1) && (ARG != 0 || expr2)) ...

Since ARG is known at compile time, the compiler will generate good code here.

Upvotes: 6

Related Questions