eliminar entradas en la lista ordenada: eficientemente en gpu

Estoy tratando de codificar el siguiente problema en cuda / thrust. Me dan una lista de claves y tres valores asociados con cada clave. He logrado clasificarlos en orden lexicográfico. La entrada ahora debe reducirse si las entradas con la misma clave tienen cada relación de valor. En el siguiente ejemplo, V1 (a) <= V1 (c) y V2 (a) <= V2 (c) y V3 (a) <= V3 (c), implica que Entrada a <Entrada c, y por lo tanto, Entrada c se elimina de la salida.

Entrada de ejemplo:

       Key      V1      V2      V3  
a.      1       2       5       3
b.      1       2       6       2
c.      1       2       7       4           
d.      1       3       6       5           
e.      2       8       8       8
f.      3       1       2       4

Salida de ejemplo:

         Key    V1  V2  V3
 a.        1    2   5   3
 b.        1    2   6   2
 e.        2    8   8   8
 f.        3    1   2   4
  • Ingrese un <Input c ==> c eliminado
  • Ingrese un <Input d ==> d eliminado

He podido resolver el problema anterior utilizando for-loops y if-sentencias. Actualmente estoy tratando de resolver esto usando cuda / thrust basado en gpu. ¿Podría hacerse esto en la gpu (preferiblemente empuje) o un kernel individual tiene que estar escrito en cuda?

No he ido a formular este problema utilizando únicos como se discutió en Thrust: Eliminación de duplicados en matrices de valores clave

Editado para incluir el programa "stl / c ++" programa para generar el escenario anterior: la sección "Reducción de myMap" es mi implementación usando for-bucles y if-sentencias.

#include <iostream>
#include <tr1/array>
#include <vector>
#include <algorithm>

struct mapItem {
    mapItem(int k, int v1, int v2, int v3){
        key=k; 
        std::tr1::array<int,3> v = {v1, v2, v3};
        values=v;
    };
    int key;
    std::tr1::array<int,3> values;
};

struct sortLexiObj{
    bool operator()(const mapItem& lhs, const mapItem& rhs){ 
        return lhs.values < rhs.values; 
    }
};
struct sortKey{
    bool operator()(const mapItem& lhs, const mapItem& rhs){ 
        return lhs.key < rhs.key; 
    }
};

int main(int argc, char** argv){

    std::vector<mapItem> myMap;

    // Set up initial matrix:
    myMap.push_back(mapItem(3, 1, 2, 4));
    myMap.push_back(mapItem(1, 2, 6, 2));
    myMap.push_back(mapItem(1, 2, 5, 3));
    myMap.push_back(mapItem(1, 3, 6, 5));
    myMap.push_back(mapItem(2, 8, 8, 8));
    myMap.push_back(mapItem(1, 2, 7, 4));

    std::sort(myMap.begin(), myMap.end(), sortLexiObj());
    std::stable_sort(myMap.begin(), myMap.end(), sortKey());
    std::cout << "\r\nOriginal sorted Map" << std::endl;
    for(std::vector<mapItem>::iterator mt=myMap.begin(); mt!=myMap.end(); ++mt){
        std::cout << mt->key << "\t";
        for(std::tr1::array<int,3>::iterator it=(mt->values).begin(); it!=(mt->values).end(); ++it){
            std::cout << *it << " ";
        }
        std::cout << std::endl;
    }
    /////////////////////////

    // Reducing myMap
    for(std::vector<mapItem>::iterator it=myMap.begin(); it!=myMap.end(); ++it){
        std::vector<mapItem>::iterator jt=it; ++jt;
        for (; jt != myMap.end();) {
            if (   (it->key == jt->key)){
                if ( it->values.at(0) <= jt->values.at(0) && 
                    it->values.at(1) <= jt->values.at(1) &&
                    it->values.at(2) <= jt->values.at(2) ) {
                    jt = myMap.erase(jt);
                } 
                else ++jt;
            }
            else break;
        }
    }

    std::cout << "\r\nReduced Map" << std::endl;
    for(std::vector<mapItem>::iterator mt=myMap.begin(); mt!=myMap.end(); ++mt){
        std::cout << mt->key << "\t";
        for(std::tr1::array<int,3>::iterator it=(mt->values).begin(); it!=(mt->values).end(); ++it){
            std::cout << *it << " ";
        }
        std::cout << std::endl;
    }

    return 0;
}

preguntado el 27 de agosto de 11 a las 17:08

Tiene problemas para identificar con precisión lo que necesita, pero parece que thrust :: unique_by_key podría ser la solución. ¿Podría publicar un enlace a su solución en serie? -

No creo thrust::unique_by_key funcionará de una manera fácil porque realiza el paso único al observar los elementos adyacentes. La solución debe considerar todos los pares posibles. -

1 Respuestas

Creo que puedes usar thrust::unique con un predicado como se muestra en Thrust: Eliminación de duplicados en matrices de valores clave. De hecho, podemos hacerlo debido a la siguiente característica de unique:

Para cada grupo de elementos consecutivos en el rango [primero, último) con el mismo valor, unique elimina todos menos el primero elemento del grupo.

Por lo tanto, debe definir un predicado para probar seudo-igualdad que volverá true para tuplas que tienen la misma clave y todos los valores son más pequeños en la primera tupla:

    typedef thrust::tuple<int, int, int, int> tuple_t;
    // a functor which defines your *uniqueness* condition
    struct tupleEqual
    {
      __host__ __device__
        bool operator()(tuple_t x, tuple_t y)
        {
          return ( (x.get<0>() == y.get<0>()) // same key
              && (x.get<1>() <= y.get<1>())   // all values are smaller
              && (x.get<2>() <= y.get<2>()) 
              && (x.get<3>() <= y.get<3>()));
        }
    };

Y tienes que aplicarlo a un ordenados colección. De esta forma, solo no se eliminará la primera tupla (la más pequeña). Una tupla con la misma clave y un valor mayor en V1, V2 o V3 producirá false para que no se elimine.

    typedef thrust::device_vector< int >                IntVector;
    typedef IntVector::iterator                         IntIterator;
    typedef thrust::tuple< IntIterator, IntIterator, IntIterator, IntIterator >   IntIteratorTuple;
    typedef thrust::zip_iterator< IntIteratorTuple >    ZipIterator;

    IntVector keyVector;
    IntVector valVector1, valVector2, valVector3;

    tupleEqual predicate;
    ZipIterator newEnd = thrust::unique(
        thrust::make_zip_iterator(
            thrust::make_tuple(
                keyVector.begin(),
                valVector1.begin(),
                valVector2.begin(),
                valVector3.begin() ) ),
        thrust::make_zip_iterator(
            thrust::make_tuple(
                keyVector.end(),
                valVector1.end(),
                valVector2.end(),
                valVector3.end() ) ),
        predicate );

    IntIteratorTuple endTuple = newEnd.get_iterator_tuple();

    keyVector.erase( thrust::get<0>( endTuple ), keyVector.end() );
    valVector1.erase( thrust::get<1>( endTuple ), valVector1.end() );
    valVector2.erase( thrust::get<2>( endTuple ), valVector2.end() );
    valVector3.erase( thrust::get<3>( endTuple ), valVector3.end() );

contestado el 23 de mayo de 17 a las 15:05

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.