簡體   English   中英

如何比較兩個BitArray並返回第二個數組的差異索引

[英]How to Compare two BitArray and return indices of differences from second array

我有兩個BitArray對象。 並想檢查值是否與第一個BitArray比較然后返回第二個數組的索引。 我嘗試遍歷每個位,但是這花費了太多時間,即:我有以下兩個對象:

BitArray a = new BitArray{true,false,true};
BitArray b = new BitArray{false,false,false};

並希望返回結果0,2,因為BitArray b與BitArray a相比有兩個變化。

如果性能是這里的主要目標,那么您將不會使用BitArray 這種抽象根本不是最優的。 您可能希望放置到自己的超大整數緩沖區,在每個緩沖區上使用“ xor”來計算增量,然后對增量使用位運算(xor結果)。


但是,在.NET Core 3上,您可以直接訪問x86指令集,從而為我們提供了SIMD和popcnt。 我們可以在這里使用SIMD XOR然后在三角洲上使用popcnt很好地結合這些東西(沒有SIMD popcnt AFAIK,但是我們可以手動展開):

        // make sure these are multiples of 128-bit, so: 4; otherwise
        // you'll have to deal with the leftover bits manually
        uint[] left = new uint[16], right = new uint[16];
        Random rand = new Random(12345);
        for (int i = 0; i < left.Length; i++)
            left[i] = (uint)rand.Next();
        for (int i = 0; i < right.Length; i++)
            right[i] = (uint)rand.Next();

        // real(ish) code starts here

        // loop over our `uint[]` as spans of Vector128<uint>
        var lspan = MemoryMarshal.Cast<uint, Vector128<uint>>(left);
        var rspan = MemoryMarshal.Cast<uint, Vector128<uint>>(right);
        uint count = 0;
        for(int i = 0; i < lspan.Length; i++)
        {
            // compute the bit delta
            var delta = Popcnt.Xor(lspan[i], rspan[i]);
            // Vector128 is 4xUInt32, so: unroll
            count += Popcnt.PopCount(delta.GetElement(0))
                + Popcnt.PopCount(delta.GetElement(1))
                + Popcnt.PopCount(delta.GetElement(2))
                + Popcnt.PopCount(delta.GetElement(3));
        }
        Console.WriteLine(count);

您也可以對xor使用更通用的Vector<T> (它也可以在.NET Framework上運行,並且可以處理比128更寬的大小),但是:那時沒有直接的popcount; 例:

        // loop over our `uint[]` as spans of Vector<uint>
        var lspan = MemoryMarshal.Cast<uint, Vector<uint>>(left);
        var rspan = MemoryMarshal.Cast<uint, Vector<uint>>(right);
        for(int i = 0; i < lspan.Length; i++)
        {
            // compute the bit delta
            var delta = lspan[i] ^ rspan[i];

            // work with delta...
        }

該( Vector<T> )通常使您的SIMD寬度為256,甚至可能為512。

如果位數組的元素計數相同,則可以使用以下代碼-

IList<int> differentIndices = new List<int>();
for(int i=0;i<a.Count;i++)
{
   if (a[i] ^ b[i])
   {
       differentIndices.Add(i);
   }
}

只需使用XOR操作

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM