【问题标题】:Implementing threads to build Smith-Watermann matrix faster实现线程以更快地构建 Smith-Watermann 矩阵
【发布时间】:2013-11-09 13:17:25
【问题描述】:

我在 C# 中执行以下循环的线程时遇到问题:

        for (int i = 1; i < matrix.scoreMatrix.GetLength(0); i++)
        {

            for (int j = 1; j < matrix.scoreMatrix.GetLength(1); j++)
            {
                matrix.CalculateScore(i, j);
            }
        }

此循环将匹配数组填充到 Smith Waterman 算法。这需要很多时间,因为我想改进填充矩阵的过程。

必须从左上角填充矩阵,因为以下单元格是根据位于上方和左侧的单元格计算的。

我的想法是利用这 2-3 个额外的线程来填充每个线阵列,如下图所示:

任何提示或类似的安排都会非常有帮助。

我做过这样的事情:

主要功能:

        int i = 0, t1_row=0, t2_row=0, t3_row=0, finished_lines=0;

        Thread t1 = new Thread(() => getnext1(matrix, i, t1_row, t2_row, t3_row, finished_lines));
        Thread t2 = new Thread(() => getnext2(matrix, i, t1_row, t2_row, t3_row, finished_lines));
        Thread t3 = new Thread(() => getnext3(matrix, i, t1_row, t2_row, t3_row, finished_lines));

        t1.Start();
        t2.Start();
        t3.Start();
        t1.Join();
        t2.Join();
        t3.Join();

线程函数:

    public static void getnext1(SWMatrix matrix, int i, int t1_row, int t2_row, int t3_row, int finished_lines)
    {
        do
        {
            for (int j = 1; j < matrix.scoreMatrix.GetLength(1); j++)
            {
                if (t1_row <= t3_row - 1 || finished_lines >= i - 2)
                {
                    matrix.CalculateScore(i, j);
                    t1_row++;
                }
                else
                {
                    j--;
                }
            }
            finished_lines++;
            i++;
            t1_row = 0;
        }
        while (i >= matrix.scoreMatrix.GetLength(0));
    }

    public static void getnext2(SWMatrix matrix, int i, int t1_row, int t2_row, int t3_row, int finished_lines)
    {
        do
        {
            for (int j = 1; j < matrix.scoreMatrix.GetLength(1); j++)
            {
                if (t2_row <= t1_row - 1 || finished_lines >= i - 2)
                {
                    matrix.CalculateScore(i, j);
                    t2_row++;
                }
                else
                {
                    j--;
                }
            }
            finished_lines++;
            i++;
            t2_row = 0;
        }
        while (i >= matrix.scoreMatrix.GetLength(0));
    }

    public static void getnext3(SWMatrix matrix, int i, int t1_row, int t2_row, int t3_row, int finished_lines)
    {
        do
        {
            for (int j = 1; j < matrix.scoreMatrix.GetLength(1); j++)
            {
                if (t3_row <= t2_row - 1 || finished_lines >= i - 2)
                {
                    matrix.CalculateScore(i, j);
                    t3_row++;
                }
                else
                {
                    j--;
                }
            }
            finished_lines++;
            i++;
            t3_row = 0;
        }
        while (i >= matrix.scoreMatrix.GetLength(0));
    }

查询执行时间几乎延长了两倍。但我也有线程工作的信息。如何优化这段代码?有什么建议吗?我在一台有 4 个处理器的机器上测试它。

【问题讨论】:

  • 您的问题是什么?您是在问这是否是一种有效/安全的方法?你问它是否会提高性能?你要的是codez吗?
  • 感谢您的回答。我对所有这些问题的答案很感兴趣。
  • 如果您在寻求有关专业/晦涩算法或数据结构的帮助时不提供链接,您本质上会将您可能获得的帮助限制在少数可能碰巧看到此内容的专家.

标签: c# multithreading matrix


【解决方案1】:

您编写的代码不正确。例如:有一个竞争条件,多个线程可以同时增加finished_lines 并产生错误的结果。您使用静态变量在线程之间进行通信的想法遇到了一个名为false sharing 的问题,并且会降低性能。 [编辑:更仔细地查看您的代码,我发现您根本没有使用共享变量。你的代码永远无法工作。]

我认为你最好使用块或瓷砖而不是单行。如果你的瓷砖是这样排列的:

A B C D ...
B C D E ...
C D E F ...
D E F G ...
. . . . ...

然后,在计算完所有先前的图块后,可以并行计算具有相同标签(在同一对角线上)的所有图块,并且您根本无需担心线程之间的同步。

这实际上比它需要的要严格一些。您需要的是波前算法。恰巧来自微软的Samples for Parallel Programming with the .NET Framework 包含一个ParallelExtensionsExtras 项目,其中包括波前算法的有效实现。这使用 .NET 4.0 或更高版本的任务并行库。

【讨论】:

  • 感谢您的回复。你有任何链接到使用块实现线程的方法吗?我不想创建一种新的低效方法。我使用框架 4.0,但我对任务并行库没有经验。在这种情况下,最好在线程上使用任务?
  • 我强烈推荐使用任务并行库。使用起来要容易得多。因为微软的人做了艰苦的工作,所以更容易编写正确的代码。在我链接到的 Microsoft 示例中,文件 ParallelAlgorithms_Wavefront.cs 包含我正在谈论的代码。
  • 我还有一个问题。我应该在 Wavefront 算法中实现我的函数 matrix.CalculateScore(i, j)。有一个方法 processRowColumnCell 但我不知道我的 matrix.CalculateScore 方法在每个单元格上执行它的确切位置。
  • 请记住我们正在处理块或图块。因此,我们有 CalculateScore(iFrom,iTo,jFrom,jTo) 而不是 CalculateScore(i,j),这反过来应该调用你的 CalculateScore(i,j)
  • 嘿。我 dont know how to do it, i suck. In file ParallelAlgorithms_Wavefront i have two overloads of functions Wavefront. Witch one i have to use? Where i have to put my CalculateScore function in this code? I have to build another overload of my function CalculateScore with 4 ints 并在调用波前函数时调用它?
猜你喜欢
  • 1970-01-01
  • 2016-03-16
  • 2021-10-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多