Тестирование на бесконечность в CUDA


В программе CUDA я недавно переключился с тестирования на inifinity с помощью

return x==INFINITY || x==-INFINITY;

Где INFINITY - из математики.h, to

return !isfinite(x);
И был весьма удивлен, получив разные результаты. gnu.org предполагает, что они действительно должны вести себя подобным образом. Я что-то упустил? Разве нельзя использовать INFINITY в ядре CUDA?

Редактировать: Я только что обнаружил isinf и заметил, что проверка с помощью

return isinf(x);

Дает тот же результат, что и проверка бесконечности. Почему? не isfinite(x)==!isinf(x)?

5 5

5 ответов:

isfinite(a) это то же самое, что !isnan(a) && !isinf(a). Если x - NaN, то и isfinite(x), и isinf(x) ложны.

isinf() проверяет только для +INFINITY или -INFINITY.

!isfinite() чеки для +INFINITY, -INFINITY или NaN.

Сравнения с плавающей точкой не обязательно корректны. Например, возможно, что (1.0f + 3.0f != 2.0f + 2.0f). вполне возможно, что isfinite считает значения, меньшие, чем определенная константа, равными бесконечности или-бесконечности, тогда как вы написали буквальное равенство.

Многие графические процессоры и SIMD-модули не полностью совместимы с IEEE754, особенно для граничных случаев вокруг бесконечностей и NaN. Только вчера вечером я заметил, что конкретный векторный процессор , с которым я работал, утверждал, что ∞+1≠ ∞, а x == x даже для X ∈ NaN.

В недавнем посте проверить, если матрица содержит значения NaN или бесконечность значений в CUDA, Роберт Crovella и предложил использовать isinf() чтобы проверить наличие бесконечного значения в CUDA.

Ниже я привожу пример проверки бесконечных значений в массиве с помощью isinf() и с использованием тяги CUDA. Возможно, это может быть полезно в качестве ссылки для других пользователей. Приведенный ниже пример эквивалентен Матлабовскому d_result=isinf(d_data);. Это отличается от примера, который я опубликовал для вопроса, приведенного выше, в том, что настоящий проверяет, что каждый отдельный элемент бесконечен, в то время как другой проверяет, содержит ли весь массив хотя бы один NaN и эквивалентен sum(isnan(d_data)); Matlab.

#include <thrust/sequence.h>

#include <thrust/device_vector.h>
#include <thrust/host_vector.h>
#include <thrust\device_vector.h>
#include <thrust\reduce.h>

#include <float.h>

// --- Operator for testing inf values
struct isinf_test { 
    __host__ __device__ bool operator()(const float a) const {
        return isinf(a);
    }
};

void main(){

    const int N = 10;

    thrust::host_vector<float> h_data(N);
    for (int i=0; i<N; i++)
        h_data[i] = rand()/RAND_MAX;

    h_data[0] = FLT_MAX/FLT_MIN;

    thrust::device_vector<float> d_data(h_data);
    thrust::device_vector<float> d_result(h_data);

    thrust::transform(d_data.begin(), d_data.end(), d_result.begin(), isinf_test());

    for (int i=0; i<N; i++) {
        float val = d_result[i];
        printf("Isinf test for element number %i equal to %f\n",i,val);
    }

    getchar();

}