Combining zwei Listen nach Schlüssel mit Thrust

Gegeben zwei Schlüsselwertlisten, versuche ich, die beiden Seiten zu kombinieren, indem ich die Schlüssel übereinstimme und eine Funktion auf die beiden Werte anwende, wenn die Schlüssel übereinstimmen. In meinem Fall möchte ich die Werte multiplizieren. Ein kleines Beispiel zur Verdeutlichung:

Left keys:   { 1, 2, 4, 5, 6 }
Left values: { 3, 4, 1, 2, 1 }

Right keys:   { 1, 3, 4, 5, 6, 7 };
Right values: { 2, 1, 1, 4, 1, 2 };

Expected output keys:   { 1, 4, 5, 6 }
Expected output values: { 6, 1, 8, 1 }

Ich konnte dies auf der CPU mit C ++ mit dem folgenden Code implementieren:

int main() {
    int leftKeys[5] =   { 1, 2, 4, 5, 6 };
    int leftValues[5] = { 3, 4, 1, 2, 1 };
    int rightKeys[6] =   { 1, 3, 4, 5, 6, 7 };
    int rightValues[6] = { 2, 1, 1, 4, 1, 2 };

    int leftIndex = 0, rightIndex = 0;
    std::vector<std::tuple<int, int>> result;
    while (leftIndex < 5 && rightIndex < 6) {
        if (leftKeys[leftIndex] < rightKeys[rightIndex]) {
            leftIndex++;
        }
        if (leftKeys[leftIndex] > rightKeys[rightIndex]) {
            rightIndex++;
        }
        result.push_back(std::make_tuple(leftKeys[leftIndex], leftValues[leftIndex] * rightValues[rightIndex]));
        leftIndex++;
        rightIndex++;
    }

    // Print results
    for (int i = 0; i < result.size(); i++) {
        std::cout << "Key: " << std::get<0>(result[i]) << "; Value: " << std::get<1>(result[i]) << "\n";
    }
}

Ich habe jedoch die Eingabetasten und Werte in Thrust'sdevice_vectors und ich brauche die Ergebnisse auch auf der GPU. Daher wäre es effizienter, wenn ich nicht alle Eingaben auf den Host und alle Ausgaben zurück auf das Gerät kopieren müsste.

Das Problem ist, dass ich keine Thrust-Funktion finden kann, mit der zwei Listen mit einem Tastensatz kombiniert werden können (und eine Funktion auf beide Werte angewendet werden kann). Existiert eine solche Funktion oder gibt es eine einfache Möglichkeit, sie selbst zu implementieren, sollte ich dies nur auf dem Host tun?

Aktualisieren

Die folgenden Annahmen können über die Eingabe getroffen werden:

Die Schlüssel werden immer sortiert.In einer einzelnen Liste gibt es keine doppelten Schlüssel (zwischen den Listen gibt es natürlich doppelte Schlüssel, sonst wäre das Ergebnis leer).

Update 2:

Während ich den zweiten Ansatz in @ Roberts Antwort implementiere, bleibe ich bei der Transformation stecken. Mein Code ist bis jetzt unten:

struct multiply_transformation : public thrust::binary_function<std::tuple<int, int>, std::tuple<int, int>, std::tuple<int, int>>
{
    __host__ __device__
        thrust::tuple<int, int> operator()(thrust::tuple<int, int> d_left, thrust::tuple<int, int> d_right)
    {
        if (thrust::get<0>(d_left) == thrust::get<0>(d_right)) {
            return thrust::make_tuple(thrust::get<0>(d_left), thrust::get<1>(d_left) * thrust::get<1>(d_right));
        }
        return thrust::make_tuple(-1, -1);
    }
};


thrust::device_vector<int> d_mergedKeys(h_leftCount + h_rightCount);
thrust::device_vector<int> d_mergedValues(h_leftCount + h_rightCount);
thrust::merge_by_key(d_leftCountKeys.begin(), d_leftCountKeys.begin() + h_leftCount,
    d_rightCountKeys.begin(), d_rightCountKeys.begin() + h_rightCount,
    d_leftCounts.begin(), d_rightCounts.begin(), d_mergedKeys.begin(), d_mergedValues.begin());

typedef thrust::tuple<int, int> IntTuple;
thrust::zip_iterator<IntTuple> d_zippedCounts(thrust::make_tuple(d_mergedKeys.begin(), d_mergedValues.begin()));
thrust::zip_iterator<IntTuple> d_zippedCountsOffset(d_zippedCounts + 1);

multiply_transformation transformOperator;
thrust::device_vector<IntTuple> d_transformedResult(h_leftCount + h_rightCount);
thrust::transform(d_zippedCounts, d_zippedCounts + h_leftCount + h_rightCount - 1, d_zippedCountsOffset, d_transformedResult.begin(), transformOperator);

Howhow, ich bekomme den Fehler, dass keine überladene Funktionthrust::transform stimmt mit der Argumentliste überein. Im obigen Codeh_leftCount undh_rightCount sind die Größen der linken und rechten Eingänge.d_leftCountKeys, d_rightCountKeys, d_leftCounts, undd_rightCounts sindthrust::device_vector<int>.

Antworten auf die Frage(6)

Ihre Antwort auf die Frage