ParOr computes the union (OR) of all provided bitmaps in parallel, where the parameter "parallelism" determines how many workers are to be used (if it is set to 0, a default number of workers is chosen)
(parallelism int, bitmaps ...*Bitmap)
| 13 | // where the parameter "parallelism" determines how many workers are to be used |
| 14 | // (if it is set to 0, a default number of workers is chosen) |
| 15 | func ParOr(parallelism int, bitmaps ...*Bitmap) *Bitmap { |
| 16 | var lKey uint32 = maxUint32 |
| 17 | var hKey uint32 |
| 18 | |
| 19 | bitmapsFiltered := bitmaps[:0] |
| 20 | for _, b := range bitmaps { |
| 21 | if !b.IsEmpty() { |
| 22 | bitmapsFiltered = append(bitmapsFiltered, b) |
| 23 | } |
| 24 | } |
| 25 | bitmaps = bitmapsFiltered |
| 26 | |
| 27 | for _, b := range bitmaps { |
| 28 | lKey = minOfUint32(lKey, b.highlowcontainer.keys[0]) |
| 29 | hKey = maxOfUint32(hKey, b.highlowcontainer.keys[b.highlowcontainer.size()-1]) |
| 30 | } |
| 31 | |
| 32 | if lKey == maxUint32 && hKey == 0 { |
| 33 | return New() |
| 34 | } else if len(bitmaps) == 1 { |
| 35 | return bitmaps[0] |
| 36 | } |
| 37 | // The following might overflow and we do not want that! |
| 38 | // as it might lead to a channel of size 0 later which, |
| 39 | // on some systems, would block indefinitely. |
| 40 | keyRange := uint64(hKey) - uint64(lKey) + 1 |
| 41 | if keyRange == 1 { |
| 42 | // All bitmaps have the same key, |
| 43 | // we can merge the 32-bit roaring bitmaps in parallel |
| 44 | var bms32s = make([]*roaring.Bitmap, 0, len(bitmaps)) |
| 45 | for _, b := range bitmaps { |
| 46 | bms32s = append(bms32s, b.highlowcontainer.containers...) |
| 47 | } |
| 48 | return roaring32AsRoaring64(roaring.ParOr(parallelism, bms32s...), lKey) |
| 49 | } |
| 50 | |
| 51 | if parallelism == 0 { |
| 52 | parallelism = defaultWorkerCount |
| 53 | } |
| 54 | // We cannot use int since int is 32-bit on 32-bit systems. |
| 55 | var chunkSize int64 |
| 56 | var chunkCount int64 |
| 57 | if int64(parallelism)*4 > int64(keyRange) { |
| 58 | chunkSize = 1 |
| 59 | chunkCount = int64(keyRange) |
| 60 | } else { |
| 61 | chunkCount = int64(parallelism) * 4 |
| 62 | chunkSize = (int64(keyRange) + chunkCount - 1) / chunkCount |
| 63 | } |
| 64 | |
| 65 | if chunkCount*chunkSize < int64(keyRange) { |
| 66 | // it's fine to panic to indicate an implementation error |
| 67 | panic(fmt.Sprintf("invariant check failed: chunkCount * chunkSize < keyRange, %d * %d < %d", chunkCount, chunkSize, keyRange)) |
| 68 | } |
| 69 | |
| 70 | chunks := make([]*roaringArray64, chunkCount) |
| 71 | |
| 72 | chunkSpecChan := make(chan parChunkSpec, minOfInt(maxOfInt(64, 2*parallelism), int(chunkCount))) |
searching dependent graphs…