【发布时间】:2016-07-24 19:03:16
【问题描述】:
我在 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。慢动作真的很糟糕。就像它需要超过 100 000 倍的时间(同时我可以计算 20 000 个神经网络 10 次,我可以使用 AMP 计算 2 个完全相同的网络)。
【问题讨论】:
-
您可以尝试在 parallel_for_each 块之后在 e 上添加同步调用。根据此处的 C++ AMP 教程msdn.microsoft.com/en-us/magazine/hh882446.aspx,应自动执行同步。但是,如果你不显式调用 synchronize(),你会丢失异常,所以也许这会出现问题?
-
我怀疑你不知道如何很好地使用AMP。您似乎坚持将产品总和累积到标量_sum [0]中。如果我理解这一点,您将强制生成的代码将所有产品发送到持有 sum[0](“大量通信”)的特定处理器,和/或强制对该总和的所有更新以执行全局锁定(“很多锁干扰”)。这些都不是有效的。我认为您最好花一些时间阅读有关数据并行编程、技术和陷阱的信息,然后利用这些知识修改您的 AMP 程序。
-
我不知道我是否可以在 e 上调用同步,但是在 _sum 上没有触发 std::exception。有没有可能,因为我在笔记本电脑上运行,GPU 不知何故处于睡眠模式,而 AMP 又回到了 cpu 上?尽管我的 CPU 使用率约为 10%,这意味着我计算机上的一个线程正在运行其 90% 的功能。
-
致 Ira Baxter:当我尝试让代码使用 _sum[idx] 时会怎样?这应该有什么不同吗,因为每个 GPU 核心都有自己的 _sum 来赋予它们的价值?
-
我测试了手动选择加速器。还是没有区别。也在不同的机器上,不同版本的视觉工作室(最初是 2015 社区,现在是 2012 终极版)。所以问题必须在代码中。我还使用相当大的计算层对整个事情进行计时:虽然 GPU 可以在大约 600-700 毫秒内完成其中一个层,但 CPU 在 0-1 毫秒内完成。
标签: c++ performance parallel-processing gpgpu c++-amp