[英]How to make my C# code faster to compute dot product
我正在尝试在C#中实现神经网络和深度学习代码。 我的教科书中的示例代码是用Python编写的,所以我试图将它们转换为C#。
我的问题是用numpy计算点积比我从头编写的C#代码快得多。
虽然我的numpy代码需要几秒钟来计算点积1000次,但我的C#代码需要更长的时间。
这是我的问题。 如何让我的C#代码更快?
这是numpy代码:
C:\temp>more dot.py
from datetime import datetime
import numpy as np
W = np.random.randn(784, 100)
x = np.random.randn(100, 784)
print(datetime.now().strftime("%Y/%m/%d %H:%M:%S"))
for i in range(0,1000):
np.dot(x, W)
print(datetime.now().strftime("%Y/%m/%d %H:%M:%S"))
C:\temp>\Python35\python.exe dot.py
2017/02/08 00:49:14
2017/02/08 00:49:16
C:\temp>
这是C#代码:
public static double[,] dot(double[,] a, double[,] b)
{
double[,] dot = new double[a0, b1];
for (int i = 0; i < a.GetLength(0); i++)
{
for (int j = 0; j < b.GetLength(1); j++)
{
// the next loop looks way slow according to the profiler
for (int k = 0; k < b.GetLength(0); k++)
dot[i, j] += a[i, k] * b[k, j];
}
}
return dot;
}
static void Main(string[] args)
{
// compatible function with np.random.randn()
double[,] W = random_randn(784, 100);
double[,] x = random_randn(100, 784);
Console.WriteLine(DateTime.Now.ToString("F"));
for (int i = 0; i < 1000; i++)
dot(W, x);
Console.WriteLine(DateTime.Now.ToString("F"));
}
问候,
Numpy通过使用BLAS进行极端优化。 使用自己的代码可能无法获得如此出色的性能。
点积虽然可以很好地并行化。 您可以考虑使用多线程,但说实话,这不值得付出努力。 只需找一个为您实现点积的库并使用它!
你的代码正在进行矩阵乘法。 存在用于进行矩阵乘法的快速算法,并且你正在做的是非常慢的O(n ^ 3)[技术上基于列/行长度的O(n * m ^ 2)]。 另外,每次分配内存并不是一个好主意。
资源为您服务:
顺便提一下,如果您想要在这种类型的东西中使用最先进的桌面性能,您可能需要查看CUDA: https : //en.wikipedia.org/wiki/CUDA
让你的C#代码就像python代码:知道什么时候你的语言跟不上大狗,当发生这种情况时,请调用常驻BLAS子系统中的本机代码,以获得高性能的并行原生优化矩阵数学运算。
常驻BLAS子系统由标准API包装。 您的C#代码将调用API,但不会知道 - 不知道是件好事! - 当前在主机上安装了哪个特定的BLAS子系统。
我喜欢OpenBLAS。 其他人喜欢英特尔MKL(?)。 还有一些人喜欢ATLAS。 我讨厌ATLAS。
如果您需要实用的解决方案 - 使用现有的库。
如果您这样做是出于娱乐/教育目的:
消除来自最内层循环的所有函数调用( GetLength
) - 任何函数调用都不能被缓存并导致显着减慢。 外环可以从相同的优化中受益,但不会带来显着的好处。
尝试首先转置第二个矩阵,以便内部循环访问两个数组的顺序元素。
尝试使用数组而不是2d数组。
Parallel.Foreach
并行化最外层循环 还可以使用Stopwatch
来测量时间 - 性能测试的精确时间测量
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.