Median Filter Implementation

I would use the MPS Median, but my median filter is slightly different - non-zero median. I have tested the implementation below with C++ compiler on the CPU and it works fine; however, I keep getting Compiler failed with XPC_ERROR_CONNECTION_INTERRUPTED error in Metal. I greatly appreciate any tip/suggestion to fix the issus.


template <typename T, size_t N>
inline T median_filter(const T vector[N], const bool is_non_zero = false) {
    // I am aware of the ineffiency of the array's copy
    T _vector[N]; _vector[0] = vector[0];

    for (size_t i = 0; i < N; i++) {
        size_t lowest = i;
        for (size_t j = i + 1; j < N; j++) {
            if (i == 0) _vector[j] = vector[j];
            if (_vector[j] < _vector[lowest]) lowest = j;
        };

        if (i != lowest) {
            const T temp = _vector[lowest];
            _vector[lowest] = _vector[i];
            _vector[i] = temp;
        };
    };

    return count % 2 == 0 ? ((_vector[N/2 - 1] + _vector[N/2]) / 2) : _vector[N/2];
};


Best,

Replies

Are you using arrays from address spaces other than thread? If so you need to overload the template for each address space you use.

Actually the array is the pixels' value from texture look-up, which is in thread address space. I tried the thread address space for the array, and I still get the compiler error.

How is count defined in your shader? Also worth noting that Metal can't deduce N without specifying the template parameters in the call, but both of these should be caught if you compile the shader offline.

Ya. I managed to get around the compiler error with a slight modification of selection sort algorithm. I avoided the copy, but I still don't think the performance is as good as the original. I only apply the filter on a window of 2x2 and 3x3, so I hope it's fine.


From what I have been experimenting, the error appears to be from accessing an array's element through a subcript using indexes other than for-loop ones. I think Metal compiler prompts that error when it cannot perform out-of-bound checking with outside for-loop indexes. And of course I test these codes with C++ compiler to ensure it work and all of indexes in bound before pasting them into Metal. I really don't know how the internal works; these are solely my speculation.

Ok, keep in mind that if you don't pass the array by reference, the array will just decay into a pointer (there is no array copy with C arrays) and the compiler won't be able to infer N from the array you pass.

Hey, this might not be relevant to you anymore, but if you're still running into XPC_ERROR_CONNECTION_INTERRUPTEDs, you might want to try checking for MTLCompilerService logs in the Console utility. Xcode doesn't ever display those, you might get info on why your code didn't compile.

Thanks so much for the tip.