Ich habe in letzter Zeit Leistungsprobleme beim Verwenden der Thrust
-Bibliothek festgestellt. Diese entstehen, wenn thrust Speicher im Basisteil einer großen verschachtelten Schleifenstruktur zuweist. Das ist offensichtlich unerwünscht, denn eine ideale Ausführung würde die Verwendung eines vorab allokierten Blocks globalen Speichers erfordern. Ich würde gerne den fehlerhaften Code auf eine der folgenden drei Arten entfernen oder verbessern:
- Implementierung eines benutzerdefinierten thrust-Speicherallocators
- Ersetzen des thrust-Codes durch CUB-Code (mit vorab allokiertem temporären Speicher)
- Schreiben eines benutzerdefinierten Kernels, um das Gewünschte zu erreichen
Obwohl die dritte Option normalerweise meine bevorzugte Wahl wäre, handelt es sich um eine copy_if
/select_if
-Art von Operation, bei der sowohl die Daten als auch die Indizes zurückgegeben werden. Das Schreiben eines benutzerdefinierten Kernels wäre wahrscheinlich eine unnötige Wiederholung und daher würde ich eine der anderen beiden Optionen bevorzugen.
Ich habe viel Gutes über CUB gehört und sehe dies daher als ideale Gelegenheit, es wirklich einzusetzen. Was ich gerne wissen würde, ist:
Wie implementiert man ein CUB select_if
mit zurückgegebenen Indizes?
Kann dies mit einem ArgIndexInputIterator
und einem Funktor wie folgt erreicht werden?
struct GreaterThan
{
int vergleich;
__host__ __device__ __forceinline__
GreaterThan(int vergleich) : vergleich(vergleich) {}
__host__ __device__ __forceinline__
bool operator()(const cub::ArgIndexInputIterator &a) const {
return (a.value > vergleich);
}
};
mit dem folgenden Code im Hauptteil des Codes:
//d_in = Geräteintarray
//d_temp_storage = ein vorab allokiierter Block
int schwellenwert;
GreaterThan select_op(schwellenwert);
cub::ArgIndexInputIterator input_itr(d_in);
cub::ArgIndexInputIterator output_itr(d_out); //????
CubDebugExit(DeviceSelect::If(d_temp_storage, temp_storage_bytes, input_itr, output_itr, d_num_selected, num_items, select_op));
Wird dies versuchen, unter der Haube irgendwelche Speicherzuweisungen vorzunehmen?
BEARBEITEN:
Also basierend auf Robert Crovellas Kommentar müsste der Funktor das Produkt aus dem Dereferenzieren eines cub::ArgIndexInputIterator
nehmen, was ein cub::ItemOffsetPair
sein sollte, wodurch der Funktor jetzt folgendermaßen aussieht:
struct GreaterThan
{
int vergleich;
__host__ __device__ __forceinline__
GreaterThan(int vergleich) : vergleich(vergleich) {}
__host__ __device__ __forceinline__
bool operator()(const cub::ItemOffsetPair &a) const {
return (a.value > vergleich);
}
};
und im Code sollte d_out
ein Gerätearray von cub::ItemOffsetPair
sein:
//d_in = Geräteintarray
//d_temp_storage = ein vorab allokiierter Block
cub::ItemOffsetPair * d_out;
//d_out zuweisen
int schwellenwert;
GreaterThan select_op(schwellenwert);
cub::ArgIndexInputIterator input_itr(d_in);
CubDebugExit(DeviceSelect::If(d_temp_storage, temp_storage_bytes, input_itr, d_out, d_num_selected, num_items, select_op));