我在C ++中有以下代码:
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。慢下来真的很糟糕。就像它需要超过10万倍(同时我可以计算10 000个神经网络10次,我可以使用AMP计算2个完全相同的网络)。
答案 0 :(得分:1)
使用sum[0]
的代码几乎肯定会给出错误的结果,因为许多线程同时更新sum[0]
。
天真的实现应该可以工作,但效率非常低,因为将数据移入和移出GPU会产生很大的复制开销,而且你的计算量非常小。
但是,它的速度和你说的一样慢,你可能正在运行CPU上的WARP加速器。您可以使用以下代码查看可用的加速器。
https://ampbook.codeplex.com/SourceControl/latest#Samples/ShowAmpDevices/ShowAmpDevices.cpp
你在这里做的是减少。关于如何在GPU上有效地执行此操作有很多文章。您可以在此处找到C ++ AMP代码,其中显示了几种不同的实现:
CodePlex上的C++ AMP: Accelerated Massive Parallelism with Microsoft Visual C++。
在与代码一起出版的书中对它们进行了全面的解释。