Created
January 20, 2021 15:55
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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