我能并行处理小于10ms的任务吗?(如矩阵反演)

本文关键字:并行处理 小于 10ms 任务 | 更新日期: 2023-09-27 17:49:22

我有一个关于Windows和Linux上的线程(或纤维)的一般性问题,在任何编程语言中:

是否有可能有一个"第二个线程待命",并让它快速跳入行动,并帮助完成一个小任务几毫秒,而不被抢占?我应该补充说,我希望没有互斥锁和自旋锁的清晰代码。

为了说明传统的线程池不适用于小任务,考虑c#中的矩阵反转问题。我在用Ivan Kuckir的矩阵类。我复制他的Invert函数,并将其命名为InvertParallel,如下所示:

public Matrix InvertParallel()   // modified from Ivan's Invert(), see link above
{
    if (L == null) MakeLU();
    Matrix inv = new Matrix(rows, cols);
    Parallel.ForEach<int>(Enumerable.Range(0, rows), rowID =>
    {
        Matrix Ei = Matrix.ZeroMatrix(rows, 1);
        Ei[rowID, 0] = 1;
        Matrix col = SolveWith(Ei);
        inv.SetCol(col, rowID);
    });
    return inv;
}

然后调用Invert和Invert_Parallel函数并测量所需的时间:

static void Main()
{
    Stopwatch sw = new Stopwatch(); sw.Start();
    Matrix A = Matrix.IdentityMatrix(50, 50);
    Matrix I1 = A.Invert();
    long elapsed1 = sw.ElapsedMilliseconds;
    Matrix I2 = A.InvertParallel();
    long elapsed2 = sw.ElapsedMilliseconds - elapsed1;
    Console.WriteLine("Matrix size=" + A.rows + ", Invert=" + elapsed1 + "ms, Invert_Parallel=" + elapsed2 + "ms");
}

相当明显的结果表明,对于小任务(矩阵大小为50),从线程池启动任务比运行单线程要慢:

Matrix size=50,  Invert=  5ms,  InvertParallel=21ms
Matrix size=100, Invert= 19ms,  InvertParallel=24ms
Matrix size=200, Invert=137ms,  InvertParallel=44ms

(抱歉-我不得不删除所有链接从下面的说明,因为我是一个新的海报)

注:可能与S/O相关的文章:'如何同时启动两个线程','Linux -线程和进程调度优先级'

注:是的,我知道有一个更聪明的算法来计算逆,它的规模是O(N^2.376)。

P.P.S.我不熟悉用户模式调度(Windows上的UMS)用户模式调度(Windows上的"UMS"),它能帮助吗?

我能并行处理小于10ms的任务吗?(如矩阵反演)

在线程之间传递任务,特别是那些与它们关联了大量数据的线程,会产生相当大的开销,正如您所看到的,这会导致小任务的性能降低。您需要找到使用多个核心更快的最佳位置。

顺便说一句,你可以得到一个小的改进,使一个工作线程,当前线程保存一个上下文切换和缓存之间的副本。例如,如果你有8个内核,传递1/7到7个其他线程,并在当前线程中执行1/8。