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

В программе CUDA я недавно переключился с тестирования на бесконечность, используя

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

где INFINITY из math.h, в

return !isfinite(x);

и был очень удивлен, получив разные результаты. gnu.org предполагает, что они на самом деле должны вести себя по аналогии. Я что-то упускаю? Разве нельзя использовать INFINITY в ядре CUDA?

Изменить: я только что обнаружил isinf и заметил, что проверка с использованием

return isinf(x);

дает тот же результат, что и проверка БЕСКОНЕЧНОСТИ. Почему нет isfinite(x)==!isinf(x)?


person hannes    schedule 03.12.2010    source источник
comment
При каких значениях результаты различались? Каковы результаты? Каковы были ожидаемые результаты?   -  person James McNellis    schedule 04.12.2010
comment
я еще не уверен, но кажется, что isfinite более строг, чем тест INFINITY.   -  person hannes    schedule 04.12.2010
comment
@stephen canon: предоставлено, но в документах Cg не упоминается макрос INFINITY из math.h, разница, о которой я спрашиваю. По-видимому, макрос INFINITY работает как isinf (см. мое редактирование), поэтому он имеет некоторое значение.   -  person hannes    schedule 04.12.2010


Ответы (5)


isfinite(a) совпадает с !isnan(a) && !isinf(a). Если x равно NaN, то и isfinite(x), и isinf(x) ложны.

person Stephen Canon    schedule 03.12.2010
comment
Моя проверка на NaN (x!=x) проходит, значит, согласно этому тесту NaN отсутствуют. Однако, если Crashworks прав, то это действительно может быть решением. - person hannes; 04.12.2010
comment
@hannes: какой графический процессор и версию CUDA вы используете? - person Stephen Canon; 04.12.2010
comment
@hannes: убедитесь, что (x!=x) не оптимизируется вашим компилятором. - person Billy ONeal; 04.12.2010
comment
@Billy ONeal: nan-тест работает правильно при ручном вводе NaN. - person hannes; 04.12.2010

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

!isfinite() проверяет наличие +INFINITY, -INFINITY или NaN.

person caf    schedule 03.12.2010

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

person Puppy    schedule 03.12.2010
comment
невероятно, что 1.0f + 3.0f != 2.0f + 2.0f на любой системе с арифметикой IEEE-754 (или даже на системах, не совсем совместимых с IEEE-754, таких как некоторые графические процессоры). Плавающая точка — это не черная магия. Существуют четко определенные правила, когда он округляется, а когда нет. - person Stephen Canon; 04.12.2010

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

person Crashworks    schedule 03.12.2010

В недавнем сообщении Проверка матрица содержит nans или бесконечные значения в CUDA, Роберт Кровелла предложил использовать isinf() для проверки бесконечных значений в CUDA.

Ниже я привожу пример проверки бесконечных значений в массиве с помощью isinf() и использования CUDA Thrust. Возможно, это могло бы быть полезно в качестве ссылки для других пользователей. Пример ниже эквивалентен d_result=isinf(d_data); в Matlab. Он отличается от примера, который я разместил для вопроса, цитируемого выше, тем, что текущий проверяет каждый отдельный элемент на бесконечность, а другой проверяет, содержит ли весь массив хотя бы один 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();

}
person Vitality    schedule 07.05.2014