c++ - Prueba de infinito en CUDA
numerical (5)
Las comparaciones de punto flotante no son necesariamente válidas. Por ejemplo, es posible que (1.0f + 3.0f != 2.0f + 2.0f)
. Es perfectamente posible que isfinite considere que los valores menores que una constante específica aparte sean iguales a INFINITE o -INFINITE, mientras que usted escribió una igualdad literal.
En un programa CUDA, recientemente cambié de las pruebas de inifinity usando
return x==INFINITY || x==-INFINITY;
donde INFINITY
es de math.h, to
return !isfinite(x);
y estaba bastante sorprendido de obtener diferentes resultados. gnu.org sugiere que en realidad deberían comportarse de manera similar. ¿Me estoy perdiendo de algo? ¿No está permitido usar INFINITY
en un núcleo CUDA?
Editar: Acabo de descubrir isinf
y noté que comprobando usando
return isinf(x);
da el mismo resultado que el cheque INFINITY. ¿Por qué is isfinite(x)==!isinf(x)
?
isfinite(a)
es lo mismo que !isnan(a) && !isinf(a)
. Si x
es NaN, entonces tanto isfinite(x)
como isinf(x)
son falsas.
isinf()
solo comprueba +INFINITY
o -INFINITY
.
!isfinite()
busca +INFINITY
, -INFINITY
o NaN
.
Muchas unidades GPU y SIMD no son totalmente compatibles con IEEE754, especialmente para casos extremos en torno a infinitos y NaN. Anoche noté que un procesador vectorial particular con el que trabajé afirmó que ∞ + 1 ≠ ∞, y x == x incluso para x & in; Yaya.
En la publicación reciente Comprobando si una matriz contiene nans o valores infinitos en CUDA , Robert Crovella sugirió usar isinf()
para verificar valores infinitos en CUDA.
A continuación, proporciono un ejemplo de comprobación de valores infinitos en una matriz utilizando isinf()
y explotando CUDA Thrust. Tal vez podría ser útil como referencia para otros usuarios. El ejemplo siguiente es equivalente a d_result=isinf(d_data);
. Es diferente del ejemplo que publiqué para la pregunta citada anteriormente en que el presente comprueba que cada elemento individual es infinito, mientras que el otro comprobó si toda la matriz contenía al menos un NaN
y era equivalente a la sum(isnan(d_data));
de Matlab sum(isnan(d_data));
.
#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();
}