Я реализую базовую программу NeuroEvolution. Набор данных, который я пытаюсь использовать, является набором данных «Тип обложки». Этот набор имеет 15 120 записей с 56 входами (числовые данные на участках лесных угодий) и 1 выходом (тип покрытия). Как рекомендовано, я использую 150 скрытых нейронов. Функция пригодности пытается перебрать все 15 120 записей, чтобы вычислить ошибку, и использовать эту ошибку для вычисления пригодности. Метод показан ниже.
double getFitness() {
double error = 0.0;
// for every record in the dataset.
for (int record = 0; record < targets.size(); record++) {
// evaluate output vector for this record of inputs.
vector<double> outputs = eval(inputs[record]);
// for every value in those records.
for (int value = 0; value < outputs.size(); value++) {
// add to error the difference.
error += abs(outputs[value] - targets[record][value]);
}
}
return 1 - (error / targets.size());
}
«входы» и «цели» — это двухмерные векторы, считываемые из файла CSV. Вся программа использует ~ 40 МБ памяти во время выполнения. Это не проблема. Программа видоизменяется из родительской сети, оба оцениваются на предмет пригодности, и наиболее подходящие параметры сохраняются для последующего изменения. Во всем процессе функция getFitness () занимает больше всего времени. Программа написана в Visual Studio 2017 (на 2.6 ГГц i7) в Windows 10.
Потребовалось ~ 7 минут, чтобы оценить работоспособность ОДНОЙ сети, используя 21% ЦП. Небольшие проблемы потребовали сотни тысяч.
Какие методы доступны, чтобы получить это число?
Программа, в которой реализовано (по-видимому) значительное использование векторов, не может быть напрямую выгружена в графический процессор с использованием OpenCL или CUDA без существенных изменений. Это делает OpenMP наиболее приемлемым вариантом. Для «параллельной работы» можно добавить всего 2 строки кода. Кроме того, Visual Studio должен быть настроен на использование OpenMP (Проект -> Свойства -> C / C ++ -> Язык -> Поддержка Open MP).
#include <omp.h>
#include <numeric>
// libraries, variables, functions, etc...
double getFitness() {
double err = 0.0;
vector<double> error;
error.resize(inputs.size());
// for every record in the dataset.
#pragma omp parallel for
for (int record = 0; record < targets.size(); record++) {
// evaluate output vector for this record of inputs.
vector<double> outputs = eval(inputs[record]);
// for every value in those records.
for (int value = 0; value < outputs.size(); value++) {
// add to error the difference.
error[record] = abs(outputs[value] - targets[record][value]);
}
}
err = accumulate(error.begin(), error.end(), 0);
return 1 - (err / targets.size());
}
В приведенном выше коде OMP должен создать поток для каждой из записей. Однако, если вы не запустите это на экземпляре облака, он будет съедать ваш процессор. Ожидайте улучшения в 4 раза для четырехъядерного процессора.
Других решений пока нет …