这是 Partitioner.Create(int fromInclusive, int toExclusive) 中的错误吗?
Is this a bug in Partitioner.Create(int fromInclusive, int toExclusive)?
我想我在方法 Partitioner.Create(int fromInclusive, int toExclusive)
中发现了一个错误。当范围超过 Int32.MaxValue
时,它会为未提供的参数 rangeSize
计算负值。这是演示该问题的代码示例:
var partitioner = Partitioner.Create(-1, Int32.MaxValue);
var partitions = partitioner.GetPartitions(1);
foreach (var partition in partitions)
{
while (partition.MoveNext())
{
var range = partition.Current;
Console.WriteLine($"Range: {range.Item1,11} => {range.Item2,11}");
}
}
输出:
Range: -1 => -178956971
Range: -178956971 => -357913941
Range: -357913941 => -536870911
Range: -536870911 => -715827881
Range: -715827881 => -894784851
Range: -894784851 => -1073741821
Range: -1073741821 => -1252698791
Range: -1252698791 => -1431655761
Range: -1431655761 => -1610612731
Range: -1610612731 => -1789569701
Range: -1789569701 => -1968526671
Range: -1968526671 => -2147483641
Range: -2147483641 => 2147483647
因此,使用 for (int i = range.Item1; i < range.Item2; i++)
循环抛出这些范围将导致除最后一个范围外的所有范围都为零循环,这将
有效循环 Int32
类型的整个范围。
有一个特例。下面的分区程序计算出 rangeSize
为 1.
Partitioner.Create(Int32.MinValue, Int32.MaxValue);
这里是方法的source code:
public static OrderablePartitioner<Tuple<int, int>> Create(
int fromInclusive, int toExclusive)
{
// How many chunks do we want to divide the range into? If this is 1, then the
// answer is "one chunk per core". Generally, though, you'll achieve better
// load balancing on a busy system if you make it higher than 1.
int coreOversubscriptionRate = 3;
if (toExclusive <= fromInclusive) throw new ArgumentOutOfRangeException("toExclusive");
int rangeSize = (toExclusive - fromInclusive) /
(PlatformHelper.ProcessorCount * coreOversubscriptionRate);
if (rangeSize == 0) rangeSize = 1;
return Partitioner.Create(CreateRanges(fromInclusive, toExclusive, rangeSize),
EnumerablePartitionerOptions.NoBuffering); // chunk one range at a time
}
似乎在减法toExclusive - fromInclusive
时发生了整数溢出。
如果这确实是一个错误,在 .NET Framework 的未来版本中修复它之前,您建议采用什么解决方法?
It seems that an integer overflow occurs on the division toExclusive -
fromInclusive.
是的,看起来是一个错误。
What workaround do you suggest until it is fixed in a future version
of the .NET Framework?
我建议将您的输入转换为 long
并改为调用 that version。 它仍然有类似的溢出错误,但如果您的原始输入是 int
,您肯定不会 运行 进入 long
的溢出场景。
@mjwills 是对的。
这是一个错误,我已记录一个问题以在 .NET Core 的未来版本中修复此问题https://github.com/dotnet/corefx/issues/40201
并且建议的解决方法也是正确的。只需将输入参数转换为 long.
我想我在方法 Partitioner.Create(int fromInclusive, int toExclusive)
中发现了一个错误。当范围超过 Int32.MaxValue
时,它会为未提供的参数 rangeSize
计算负值。这是演示该问题的代码示例:
var partitioner = Partitioner.Create(-1, Int32.MaxValue);
var partitions = partitioner.GetPartitions(1);
foreach (var partition in partitions)
{
while (partition.MoveNext())
{
var range = partition.Current;
Console.WriteLine($"Range: {range.Item1,11} => {range.Item2,11}");
}
}
输出:
Range: -1 => -178956971
Range: -178956971 => -357913941
Range: -357913941 => -536870911
Range: -536870911 => -715827881
Range: -715827881 => -894784851
Range: -894784851 => -1073741821
Range: -1073741821 => -1252698791
Range: -1252698791 => -1431655761
Range: -1431655761 => -1610612731
Range: -1610612731 => -1789569701
Range: -1789569701 => -1968526671
Range: -1968526671 => -2147483641
Range: -2147483641 => 2147483647
因此,使用 for (int i = range.Item1; i < range.Item2; i++)
循环抛出这些范围将导致除最后一个范围外的所有范围都为零循环,这将
有效循环 Int32
类型的整个范围。
有一个特例。下面的分区程序计算出 rangeSize
为 1.
Partitioner.Create(Int32.MinValue, Int32.MaxValue);
这里是方法的source code:
public static OrderablePartitioner<Tuple<int, int>> Create(
int fromInclusive, int toExclusive)
{
// How many chunks do we want to divide the range into? If this is 1, then the
// answer is "one chunk per core". Generally, though, you'll achieve better
// load balancing on a busy system if you make it higher than 1.
int coreOversubscriptionRate = 3;
if (toExclusive <= fromInclusive) throw new ArgumentOutOfRangeException("toExclusive");
int rangeSize = (toExclusive - fromInclusive) /
(PlatformHelper.ProcessorCount * coreOversubscriptionRate);
if (rangeSize == 0) rangeSize = 1;
return Partitioner.Create(CreateRanges(fromInclusive, toExclusive, rangeSize),
EnumerablePartitionerOptions.NoBuffering); // chunk one range at a time
}
似乎在减法toExclusive - fromInclusive
时发生了整数溢出。
如果这确实是一个错误,在 .NET Framework 的未来版本中修复它之前,您建议采用什么解决方法?
It seems that an integer overflow occurs on the division toExclusive - fromInclusive.
是的,看起来是一个错误。
What workaround do you suggest until it is fixed in a future version of the .NET Framework?
我建议将您的输入转换为 long
并改为调用 that version。 它仍然有类似的溢出错误,但如果您的原始输入是 int
,您肯定不会 运行 进入 long
的溢出场景。
@mjwills 是对的。
这是一个错误,我已记录一个问题以在 .NET Core 的未来版本中修复此问题https://github.com/dotnet/corefx/issues/40201
并且建议的解决方法也是正确的。只需将输入参数转换为 long.