【问题标题】:Parallelizing very large array base conversion并行化非常大的数组基础转换
【发布时间】:2014-03-24 22:12:27
【问题描述】:

我有一个方法可以将 value 转换为 newBase 长度 length 数。

英文的逻辑是:

If we calculated every possible combination of numbers from 0 to (c-1)
with a length of x
what set would occur at point i

虽然下面的方法工作得很好,但由于使用了非常大的数字,可能需要很长时间才能完成:

例如,在 64 位架构、四核 PC 上完成 value=((((65536^480000)-1)/2)、newbase=(65536)、length=(480000) 大约需要一个小时)。

private int[] GetValues(BigInteger value, int newBase, int length)
{
    Stack<int> result = new Stack<int>();

    while (value > 0)
    {
        result.Push((int)(value % newBase));

        if (value < newBase)
            value = 0;
        else
            value = value / newBase;
    }

    for (var i = result.Count; i < length; i++)
    {
        result.Push(0);
    }

    return result.ToArray();
}

我的问题是,我怎样才能将此方法更改为允许多个线程计算部分数字的方法?

我正在使用 C#,但如果你不熟悉它,那么伪代码也可以。

注意:方法来自这个问题:Cartesian product subset returning set of mostly 0

【问题讨论】:

  • “我的问题是,我怎样才能将这种方法更改为允许多个线程计算出部分数字的方法?” ---这是一个错误的问题。您最好并行处理原始数字数组。因此,这种精确的方法可以针对不同的数字并行运行。只要这是pure function - 它应该是微不足道的。
  • 虽然我同意你的观点,但我不确定如何改写我的问题以反映这一点。你介意编辑一下吗?
  • “可能需要很长时间才能完成。” ---你可以从澄清这一点开始。使用线程进行编程会带来一些开销并使代码更加复杂。让我们从确保它是必需的开始。
  • @zerkms:我已经用一个例子澄清了“很长时间”
  • @HenkHolterman:这是个好主意,我认为 Stack 会更快,我看看是否可以将其更改为 int 数组。

标签: c# multithreading math set-theory


【解决方案1】:

如果GetValues 方法确实是瓶颈,您可以采取一些措施来加快速度。

首先,每次循环都除以newBase。由于newBaseint,并且BigInteger 除法除以BigInteger,因此您可能会在每次迭代中产生intBigInteger 转换的成本。您可以考虑:

BigInteger bigNewBase = newBase;

此外,您可以通过调用DivRem 将分割次数减半:

while (value > 0)
{
    BigInteger rem;
    value = BigInteger.DivRem(value, bigNewBase, out rem);
    result.Push((int)rem);
}

正如在 cmets 中提到的那样,另一种优化是将数字存储在预先分配的数组中。您必须致电 Array.Reverse 以按正确顺序获取它们,但这几乎不需要时间。

顺便说一下,这种方法不适合并行化,因为计算每个数字都依赖于前一个数字的计算。

【讨论】:

  • 我尝试了您的一些建议,您对转移到 int 数组并使用 DivRem 是正确的,这些共同加快了我在大型测试中的例程大约 30%。但是,将 newBase 用作 BigInteger 实际上使该过程稍微慢了一点,持续增加了大约一秒的运行时间(以前大约是 7 秒,所以不多)。作为后续问题,您是否认为可以将 here 采用的方法转换为使用数字而不是 char[],因为它看起来很容易并行化。
  • @Transmission:我很惊讶将newBase 转换为BigInteger 会减慢速度。您是否正在使用调试器 detached 运行发布版本(即,如果您在 Visual Studio 中,则使用 Ctrl+F5)?另外,你的时间安排如何?
  • @Transmission:我看不出您链接的答案如何适用于这个问题。这个答案只是从一个集合中创建组合——你可以并行化的东西(尽管它可能不值得)。在那里,选择的各个值彼此独立。在您的基本转换问题中,每个结果都取决于先前的结果。也就是说,在计算完第一个数字之前,您无法计算第二个数字,而第三个数字取决于第二个数字,依此类推。
  • 我正在运行调试版本,并附加了调试器,因为这是我的单元测试之一。我使用 Stopwatch 对象进行计时,这是我常用的方法。我会使用分析器,但它似乎不想在我的电脑上工作。至于第二点,这种方法的最终结果是“如果我们计算从 0 到 (c-1) 的每个可能的数字组合,长度为 x,在点 i 会出现什么集合”,并且这个映射 (我认为)对我链接的答案非常好,它对字符数组而不是数字执行此操作。
  • 我一直将其称为基本转换问题的原因是因为其他人是这样解释它的,这是有道理的,但就像我说的那样,最终的游戏是获得第 i 个可能一组数字。
猜你喜欢
  • 1970-01-01
  • 2017-03-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-07
  • 2016-04-07
  • 1970-01-01
相关资源
最近更新 更多