如何使我的C#代码更快地计算点积

3

我想在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"));
}

敬礼,


为什么要从头开始实现神经网络?如果这只是一个学习练习,那么代码运行速度并不重要。如果目的是让东西运行得好,那么使用已经编写好的高质量软件就更好了。像TensorFlow、H2O、Torch这样的神经网络模型包有很多,它们都比一个人用C#制作的工程更好,具有更多的功能和更高的速度。 - Geoffrey Anderson
没错。这只是为了我学习C#和深度学习,但我发现计算点积比我预期的要慢得多,而且我在我的教科书中运行示例(移植到C#)时感到很痛苦。因此,我想提高性能。我将使用一些现有的库来实现未来生产系统的性能和更好的实现。 - snaga
4个回答

2

Numpy通过使用BLAS进行极度优化。使用您自己的代码可能不会获得如此出色的性能。

点积非常适合并行处理。您可以考虑多线程工作,但说实话,这并不值得。只需寻找一个实现点积的库并使用它即可!


谢谢!我想在C#中尝试使用OpenBLAS。 - snaga

2

谢谢!我对矩阵运算及其优化还不熟悉,所以我打算学习它。同时也会学习CUDA技术。 - snaga

1
让你的C#代码像Python代码一样:知道当你的语言无法跟上大牛时,就调用本地BLAS子系统中的原生代码,以获得高性能并行本地优化矩阵数学运算。
本地BLAS子系统由标准API包装。您的C#代码将调用API,但不会知道 -- 不知道是一件好事! -- 当前安装在主机上的特定BLAS子系统是哪个。
我喜欢OpenBLAS。其他人喜欢Intel MKL(?)。还有人喜欢ATLAS。我讨厌ATLAS。

知道当你的编程语言无法跟上大牛时,该如何处理。当出现这种情况时,请调用驻留 BLAS 子系统中的本地代码,进行高性能并行本地优化矩阵数学运算。是的,实际上,这正是我想学习的内容,我认为是时候学习 BLAS 以及如何从 C# 中调用它了。谢谢! - snaga

1

如果您需要实际解决方案-请使用现有的库。
如果您是为了娱乐/教育目的而这样做:
- 从最内层循环(GetLength)中消除所有函数调用-任何函数调用都不能被缓存,并导致显著的减速。外部循环可能会受益于同样的优化,但不会带来显著的好处。 - 尝试先转置第二个矩阵,以便内部循环访问两个数组的连续元素。 - 尝试使用数组的数组而不是2d数组。 - 使用数组的数组时,请尝试在内循环中使用Length-这可以消除至少一个数组上的边界检查。 - 尝试使用Parallel.Foreach并行化最外层循环。 - 如果实际问题需要多次非方阵矩阵乘法-请参考 https://en.wikipedia.org/wiki/Matrix_chain_multiplication - 还要使用Stopwatch来测量时间-性能测试的精确时间测量

感谢您提供的绝佳技巧! 是的,我对C#和神经网络/深度学习都很新,所以这是我的玩具项目,让我掌握C#和神经网络/深度学习算法。 我正在寻找性能提示,以在C#中实现数字算法。我想尽快尝试您的技巧。 再次感谢! - snaga

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接