я следующий код в C++:C++ AMP медленно
float Neuron::feedForward(std::vector<Neuron>& previousLayer){
float sum=0.0f;
for(int i=0;i<(int)previousLayer.size();i+=1){
sum+=previousLayer[i].getOutput()*weigths[i];
}
output=Neuron::transferFunction(sum);
return output;
};
Это я преобразованного к этому:
float Neuron::feedForward(std::vector<Neuron>& previousLayer){
float sum=0.0f;
extent<1> e((int)previousLayer.size());
std::vector<float> ops(previousLayer.size());
for (int i = 0; i<(int)previousLayer.size(); i += 1) {
ops[i] = previousLayer[i].getOutput();
}
array_view<const float, 1>_outputs(e, ops);
array_view<const float, 1>_weigths(e, weigths);
array_view<float> _sum(e);
_sum.discard_data();
parallel_for_each(e, [=](index<1> idx) restrict(amp) {
_sum[idx] = _outputs[idx] * _weigths[idx];
});
for (int i = 0; i < e[0]; i += 1) {
sum += _sum[i];
}
output=Neuron::transferFunction(sum);
return output;
};
Теперь программа запускает код очень медленно. Не менее нескольких миллисекунд медленнее, но фактические секунды медленнее.
Я также попытался иметь сумму внутри кода AMP (только изменения):
array_view<float> _sum(1);
_sum.discard_data();
...
parallel_for_each(e, [=](index<1> idx) restrict(amp) {
_sum[0] += _outputs[idx] * _weigths[idx];
});
...
/*for (int i = 0; i < e[0]; i += 1) {
sum += _sum[i];
}
*/
output=Neuron::transferFunction(_sum[0]);
Но, в конце концов, код таков: так медленно, что я бы быстрее с калькулятором руки. Теперь вопрос: зачем? Я думал, что если бы у меня был нейрон с 2000 весовыми коэффициентами, было бы здорово, если бы GPU вычислил все. Я что-то упускаю, или мне нужно изучать OpenCL или CUDA?
PS. Сливы действительно плохие. Как и требуется более 100 000 раз дольше (в то же время я могу вычислить 20 000 нейронных сетей десять раз, я могу вычислить 2 точно такие же сети, используя AMP).
Вы можете попробовать добавить вызов синхронизации по e после блока parallel_for_each. В соответствии с инструкцией C++ AMP, https://msdn.microsoft.com/en-us/magazine/hh882446.aspx, синхронизация должна выполняться автоматически. Но, если вы не вызываете synchronize() явно, вы потеряете исключения, так что, может быть, это что-то изменит? – hacoo
Я подозреваю, что вы не знаете, как хорошо использовать AMP. Кажется, вы настаиваете на накоплении суммы продуктов в скалярном _sum [0]. Если я понимаю это право, вы вынуждаете сгенерированный код отправлять все продукты конкретному процессору, который содержит сумму [0] («много сообщений») и/или принуждает все обновления к этой сумме выполнять глобальную блокировку (" много помех блокировки "). Ни один из них не эффективен. Я думаю, вам будет полезно потратить некоторое время на чтение данных о параллельном программировании, методах и подводных камнях, а затем использовать эти знания для пересмотра вашей программы для AMP. –
Я не знаю, могу ли я вызвать синхронизацию по e, но на _sum не было вызвано std :: exception.Возможно ли, что, поскольку я бегу на ноутбуке, графический процессор каким-то образом находится в режиме сна, а AMP падает на CPU? Хотя использование моего процессора составляет ~ 10%, что означает, что один из потоков на моем компьютере работает на 90% от его возможностей. – Nyxeria