2010-12-03 22 views
5

In einem CUDA-Programm, wechselte ich vor kurzem von Tests für inifinityTesting für die Unendlichkeit in CUDA

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

mit dem INFINITY aus math.h ist, zu

return !isfinite(x); 

und war ziemlich überrascht zu bekommen verschiedene Ergebnisse. gnu.org schlägt vor, dass sie sich tatsächlich ähnlich verhalten sollten. Fehle ich etwas? Ist es nicht erlaubt INFINITY in einem CUDA Kernel zu verwenden?

Edit: ich isinf gerade entdeckt, und bemerkte, dass

return isinf(x); 

gibt das gleiche Ergebnis wie die INFINITY Prüfung mit Kontrolle. Warum ist isfinite(x)==!isinf(x) nicht?

+0

Für welche Werte unterschieden sich die Ergebnisse? Was waren die Ergebnisse? Was waren die erwarteten Ergebnisse? –

+0

Ich bin mir noch nicht sicher, aber es scheint, dass isfinite strenger ist als der INFINITY-Test. – hannes

+0

@stephen canon: gewährt, aber die Cg-Dokumente erwähnen nicht das INFINITY-Makro von math.h, der Unterschied, nach dem ich frage. Anscheinend funktioniert das INFINITY-Makro wie isinf (siehe meine Bearbeitung), also hat es einige Relevanz. – hannes

Antwort

5

isfinite(a) ist das gleiche wie !isnan(a) && !isinf(a). Wenn x NaN ist, sind sowohl isfinite(x) als auch isinf(x) falsch.

+0

Meine Prüfung auf NaN '(x! = X)' besteht, also gibt es nach diesem Test keine NaNs. Wenn Crashworks jedoch recht hat, könnte dies tatsächlich die Lösung sein. – hannes

+0

@hannes: Welche GPU und Version von CUDA verwendest du? –

+2

@hannes: Stellen Sie sicher, dass '(x! = X)' von Ihrem Compiler nicht optimiert wird. –

1

Gleitkommavergleiche sind nicht unbedingt gültig. Zum Beispiel ist es möglich, dass (1.0f + 3.0f != 2.0f + 2.0f). Es ist durchaus möglich, dass isfinite Werte kleiner als eine bestimmte Konstante betrachtet, um INFINITE oder -INFINITE gleich zu sein, während Sie eine buchstäbliche Gleichheit geschrieben haben.

+11

Es ist ** nicht ** möglich, dass '1.0f + 3.0f! = 2.0f + 2.0f' auf irgendeinem System mit der IEEE-754-Arithmetik (oder sogar auf Systemen, die nicht ganz IEEE-754-konform sind wie einige GPUs). Fließkomma ist keine schwarze Magie. Es gibt klar definierte Regeln für die Rundenzeit und wann nicht. –

1

Viele GPUs und SIMD-Einheiten sind nicht vollständig IEEE754-konform, insbesondere für Randfälle um Unendlichkeiten und NaNs. Gerade letzte Nacht bemerkte ich, dass ein bestimmter Vektorprozessor, mit dem ich arbeitete, behauptete, dass ∞ +1 ≠ ∞ und x == x sogar für x ∈ NaN.

2

isinf() wird nur für +INFINITY oder -INFINITY geprüft.

!isfinite() prüft auf +INFINITY, -INFINITY oder NaN.

0

In dem letzten Beitrag Checking if a matrix contains nans or infinite values in CUDA hat Robert Crovella vorgeschlagen, isinf() zu verwenden, um nach unendlichen Werten in CUDA zu suchen.

Unten gebe ich ein Beispiel für die Überprüfung auf unendliche Werte in einem Array mit isinf() und durch die Nutzung von CUDA Thrust. Vielleicht könnte es als Referenz für andere Benutzer nützlich sein. Das folgende Beispiel entspricht Matlabs d_result=isinf(d_data);. Es unterscheidet sich von dem Beispiel, das ich für die oben zitierte Frage geschrieben habe, darin, dass das vorliegende prüft, ob jedes einzelne Element unendlich ist, während das andere prüfte, ob das gesamte Array mindestens eine NaN enthielt und Matlabs sum(isnan(d_data)); entsprach.

#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(); 

}