【问题标题】:Multi-threaded operations多线程操作
【发布时间】:2016-08-29 13:10:31
【问题描述】:

我正在使用 Math.Net 解决三对角系统。我已经安装了 MKL (x86) 和 OpenBLAS 扩展,但显然当我看到 CPU 使用率时,我只看到一个内核在工作。这是代码

MathNet.Numerics.Control.UseNativeMKL();
MathNet.Numerics.Control.UseMultiThreading();

Matrix<double> A;
Vector<double> x;
Vector<double> b;
// *** FILL A and B ***

for (int n = 0; n < 50000; n++)
    x = A.Solve(b);

这当然是实际代码的一个非常简化的版本,但对于使用超过 1 个 CPU 没有任何帮助。

代码是在启用了优化的版本中编译的,我尝试了“任何 CPU”和“x64”。

我做错了吗?

[编辑] 忘了提,但 A 和 b 可能会在 for 循环期间发生变化,因此,我无法并行化 for 循环。这个问题更倾向于“如何强制 Math.Net 使用其 LA 提供程序的多线程包装器?”

【问题讨论】:

  • 我假设您希望 A.Solve(b) 使用多线程实现?
  • 是的,根据 Math.Net(它只是原生提供者的包装器),如果原生提供者(即 MKL 或 OpenBLAS)使用多个线程,则每个操作(例如 Solve、Multiply 等)都会使用多个线程。也应该是多线程的
  • 您的矩阵有多大?使用多线程仅在大型系统上有效,这就是为什么 Math.NET 线性代数提供程序仅在小型矩阵上使用调用线程。
  • 矩阵是 128 x 128,有点小。我认为使用“UseMultiThreading”我以某种方式强制该开关始终打开,无论问题维度如何

标签: c# multithreading intel-mkl mathnet-numerics openblas


【解决方案1】:

CPU 型号(任何 CPU、x64 等)与内核的使用无关。如果输出代码必须是 32 位、64 位或两者兼有,它只是定义编译器。

我猜Solve 方法没有使用多线程,但也许您可以在多个线程/内核上执行繁重的工作:

尝试使用 Parallel.For 方法:

Parallel.For(0, 5000, n => x = A.Solve(b));

这将创建一个 for 循环,但所有迭代都在机器的核心上进行。

注意#1:由于您的代码是一个简化版本,我希望您可以将我的答案翻译成您的实际代码,因为您的示例似乎只是重复相同的操作 5000 次。

注意#2:如果实例 A 或 b 被方法 Solve 修改,此解决方案将不起作用,因为多个线程会同时修改这些对象,这将导致不可预知的结果。

来源:https://msdn.microsoft.com/en-us/library/dd460713(v=vs.110).aspx

【讨论】:

  • 感谢您的回答。实际上是的,所有变量都取决于 for 循环的上一次迭代,因此,我无法真正并行化它。但我知道(根据 Math.Net 文档)所有 LA 操作都应该使用所有可能的内核并行化..
  • 你有消息来源吗?该声明写在哪里?
  • 从这个 (github.com/mathnet/mathnet-numerics/commit/…) 我看到选项 UseMultiThreading 应该使用所有线程,即使对于本机提供程序