Change:
Not sure what is the reason for these errors, any suggestions? I suspect the clang version is not supported? Here is the
clang have more strict checking , pull request will fixed it.
fixed, thanks to

Discussion:
static inline __host__ __device__  char mul(char a, char b) { return a * b; } static inline __host__ __device__  char sub(char a, char b) { return a - b; } static inline __host__ __device__  char div(char a, char b) { return a / b; } <del> static inline __host__ __device__  char abs(char a) { return abs(a); } </del> <ins> static inline __host__ __device__  char abs(char a) { return ::abs((int)a); } </ins> }; template <>

static inline __host__ __device__  short mul(short a, short b) { return a * b; } static inline __host__ __device__  short sub(short a, short b) { return a - b; } static inline __host__ __device__  short div(short a, short b) { return a / b; } <del> static inline __host__ __device__  short abs(short a) { return abs(a); } </del> <ins> static inline __host__ __device__  short abs(short a) { return ::abs((int)a); } </ins> }; template <>

blockIdx.x; } <del> // Block-wide reduction in shared memory helper; only threadIdx.x == 0 will // return the reduced value template <typename T, typename ReduceOp> __device__ T reduceBlock(T* smem, int numVals, T threadVal, ReduceOp reduceOp, T init) { </del> <ins> // Reduce N values concurrently, i.e. suppose N = 2, and there are 4 threads: // (1, 2), (3, 4), (5, 6), (7, 8), then the return in threadVals for thread 0 // is (1 + 3 + 5 + 7, 2 + 4 + 6 + 8) = (16, 20) template <typename T, typename ReduceOp, int N> __device__ void reduceNValuesInBlock(T *smem, T threadVals[N], int numVals, ReduceOp reduceOp, T init) { </ins> if (numVals == 0) { <del> return init; </del> <ins> #pragma unroll for (int i = 0; i < N; ++i) { threadVals[i] = init; } return; </ins> } <ins> // We store each of the N values contiguously, so if N = 2, all values for // the first threadVal for each thread in the block are stored followed by // all of the values for the second threadVal for each thread in the block </ins> if (threadIdx.x < numVals) { <del> smem[threadIdx.x] = threadVal; </del> <ins> #pragma unroll for (int i = 0; i < N; ++i) { smem[i * numVals + threadIdx.x] = threadVals[i]; } </ins> } <del> // First warp will perform reductions across warps </del> __syncthreads(); <del> if ((threadIdx.x / warpSize) == 0) { T r = threadIdx.x < numVals ? smem[threadIdx.x] : init; </del> <ins> // Number of lanes in the final reduction --> this is used to determine // where to put the outputs of each of the n things we are reducing. If // nLP = 32, then we have the 32 outputs for the first threadVal, // followed by the 32 outputs for the second threadVal, etc. int numLanesParticipating = min(numVals, warpSize); if (numVals > warpSize && ((threadIdx.x / warpSize) == 0 )) { #pragma unroll for (int i = 0; i < N; ++i) { threadVals[i] = threadIdx.x < numVals ? threadVals[i] : init; } </ins> for (int i = warpSize + threadIdx.x; i < numVals; i += warpSize) { <del> r = reduceOp(r, smem[i]); </del> <ins> #pragma unroll for (int j = 0; j < N; ++j) { threadVals[j] = reduceOp(threadVals[j], smem[j * numVals + i]); } </ins> } <del> smem[threadIdx.x] = r; </del> <ins> #pragma unroll for (int i = 0; i < N; ++i) { smem[i * numLanesParticipating + threadIdx.x] = threadVals[i]; } </ins> } <del> // First thread will perform reductions across the block </del> __syncthreads(); <del> T r = init; </del> if (threadIdx.x == 0) { <del> r = smem[0]; int numLanesParticipating = min(numVals, warpSize); </del> if (numLanesParticipating == 32) { <del> // Unroll for warpSize == 32 and numVals >= 32 </del> #pragma unroll <del> for (int i = 1; i < 32; ++i) { r = reduceOp(r, smem[i]); </del> <ins> for (int i = 0; i < N; ++i) { #pragma unroll for (int j = 1; j < 32; ++j) { threadVals[i] = reduceOp(threadVals[i], smem[i * 32 + j]); } </ins> } } else { <del> for (int i = 1; i < numLanesParticipating; ++i) { r = reduceOp(r, smem[i]); </del> <ins> #pragma unroll for (int i = 0; i < N; ++i) { for (int j = 1; j < numLanesParticipating; ++j) { threadVals[i] = reduceOp(threadVals[i], smem[i * numVals + j]); } </ins> } } } <ins> } </ins> <del> return r; </del> <ins> // Block-wide reduction in shared memory helper; only threadIdx.x == 0 will // return the reduced value template <typename T, typename ReduceOp> __device__ T reduceBlock(T* smem, int numVals, T threadVal, ReduceOp reduceOp, T init) { reduceNValuesInBlock<T, ReduceOp, 1>(smem, &threadVal, numVals, reduceOp, init); return threadVal; </ins> } // Block-wide reduction where each thread locally reduces N // values before letting a single warp take over - assumes // threadVals is in registers, not shared memory template <typename T, typename ReduceOp, int N> <del> __device__ T reduceBlockN(T *smem, </del> <ins> __device__ T reduceBlockWithNThreadLocalReductions(T *smem, </ins> T threadVals[N], int numVals, ReduceOp reduceOp,

struct ModeUnsignedPair max = {0, 0}; <del> max = reduceBlockN<struct ModeUnsignedPair, MaxReduceOp<struct ModeUnsignedPair>, 2> </del> <ins> max = reduceBlockWithNThreadLocalReductions<struct ModeUnsignedPair, MaxReduceOp<struct ModeUnsignedPair>, 2> </ins> (uupmem, uup, sliceSize, MaxReduceOp<struct ModeUnsignedPair>(), max); // Store the mode in shared memory for use in finding the mode in the input slice

// with the mode. struct ModeUnsignedBoolPair match = {0, false}; <del> match = reduceBlockN<struct ModeUnsignedBoolPair, MatchReduceOp<struct ModeUnsignedBoolPair>, 2> </del> <ins> match = reduceBlockWithNThreadLocalReductions<struct ModeUnsignedBoolPair, MatchReduceOp<struct ModeUnsignedBoolPair>, 2> </ins> (ubpmem, ubpp, sliceSize, MatchReduceOp<struct ModeUnsignedBoolPair>(), match); // Finally, we have the mode, and an index where it occurs. We use a single thread