Skip to content

Instantly share code, notes, and snippets.

@john-h-k
Created January 20, 2021 15:55
public class IsPow2Benchmark
{
private const int Iterations = 1024;
public int[] Values { get; } = new int[Iterations];
private volatile bool _result;
public enum DataType { Zero, Random, UniformPow2, UniformNonPow2, UniformNegative, Alternating, AlternatingSign }
[Params(DataType.Zero, DataType.Random, DataType.UniformPow2, DataType.UniformNonPow2, DataType.UniformNegative, DataType.Alternating, DataType.AlternatingSign)]
public DataType Type;
[GlobalSetup]
public void Setup()
{
switch (Type)
{
case DataType.Random:
{
using var rng = RandomNumberGenerator.Create();
rng.GetBytes(MemoryMarshal.AsBytes<int>(Values));
break;
}
case DataType.UniformPow2:
Values.AsSpan().Fill(1 << 6);
break;
case DataType.UniformNonPow2:
Values.AsSpan().Fill((1 << 6) + 1);
break;
case DataType.UniformNegative:
Values.AsSpan().Fill(-(1 << 6));
break;
case DataType.Alternating:
for (int i = 0, j = 1; j < Values.Length; i++, j++)
{
Values[i] = 1 << 6;
Values[i] = (1 << 6) - 1;
}
break;
case DataType.AlternatingSign:
for (int i = 0, j = 1; j < Values.Length; i++, j++)
{
Values[i] = 1 << 6;
Values[i] = -(1 << 6);
}
break;
case DataType.Zero:
Values.AsSpan().Clear();
break;
}
}
[Benchmark]
public void IsPow2_Branch_Popcnt_Random()
{
foreach (var val in Values)
{
_result = IsPow2_Branch_Popcnt(val);
}
}
[Benchmark]
public void IsPow2_Branch_Software_Random()
{
foreach (var val in Values)
{
_result = IsPow2_Branch_Software(val);
}
}
[Benchmark]
public void IsPow2_BranchInverted_Software_Random()
{
foreach (var val in Values)
{
_result = IsPow2_BranchInverted_Software(val);
}
}
[Benchmark]
public void IsPow2_Branchless_Popcnt_Random()
{
foreach (var val in Values)
{
_result = IsPow2_Branchless_Popcnt(val);
}
}
public bool IsPow2_Branch_Popcnt(int value) => value >= 0 && Popcnt.PopCount((uint)value) == 1;
public bool IsPow2_Branchless_Popcnt(int value)
{
uint unsigned = (uint)value;
uint mask = unsigned >> 31;
return (Popcnt.PopCount(unsigned) & ~mask) == 1;
}
public bool IsPow2_Branch_Software(int value) => (value & (value - 1)) == 0 && value >= 0;
public bool IsPow2_BranchInverted_Software(int value) => value >= 0 && (value & (value - 1)) == 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment