C ++ 17 параллельных алгоритмов на контейнерах с объектными данными - PullRequest
1 голос
/ 08 апреля 2020

Я пытаюсь использовать параллельные алгоритмы C ++ 17 с контейнерами, содержащими неосновные типы, как показано в минимальном примере ниже, скомпилированном с использованием GCC9.2.1 / Intel TBB в Ubuntu 19.10. Последовательная политика в порядке, но компиляция завершается неудачно с par, поскольку ожидается, что лямбда-выражение принимает double в качестве второго аргумента. Проблема сохраняется на i cc 19.0.1. У меня вопрос, если код действителен или эта проблема просто из-за ранней стадии разработки параллельной реализации?

#include <numeric>
#include <algorithm>
#include <execution>
#include <vector>

struct Data {
    double radius;
};

int main() {
    double sum;
    std::vector<double> v1;
    std::vector<Data> v2;

    // ok
    sum = std::reduce(std::execution::par, v1.begin(), v1.end(), 0.0, [](double sum, auto i) { return sum + i; });

    // ok
    sum = std::reduce(std::execution::seq, v2.begin(), v2.end(), 0.0, [](double sum, const Data &i) { return sum + i.radius; });

    // compile error
    sum = std::reduce(std::execution::par, v2.begin(), v2.end(), 0.0, [](double sum, const Data &i) { return sum + i.radius; });
}

1 Ответ

2 голосов
/ 08 апреля 2020

BinaryOp для std::reduce должно быть коммутативным, ниже должны поддерживаться обе операции:

double + Data // your lambda supports only this 
Data + double // this can be performed only by adding some conversions

Если вы хотите выполнить преобразование double->Data, вам следует добавить соответствующий конструктор. Для конвертации Data->double необходимо добавить соответствующий оператор конвертации:

struct Data {
    double radius;

    // double -> Data
    Data (double d) : radius(d) {}

    // Data -> double
    operator double() const {
        return radius;
    }
};

Демо-версия

...