簡體   English   中英

在漢明立方體的頂點上的查詢點

[英]Query points on the vertices of a Hamming cube

我有N個點,它們僅位於維度D的多維數據集的頂點上,其中D等於3。

頂點可能不包含任何點。 因此,每個點的坐標都為{0,1} D。 我只對查詢時間感興趣,只要內存成本合理(例如,在N中不是指數):)。

給定一個查詢,該查詢位於多維數據集的一個頂點上,並且輸入參數為r ,請找到該查詢的漢明距離 <= r所有頂點(因此是點)。

環境中應該采取什么方式?


我正在考慮一個kd樹,但是我不確定並且想要幫助,任何輸入,甚至是近似輸入,都將不勝感激! 由於漢明距離起作用,因此按位操作應有所幫助(例如XOR)。

從一個設置了k位的位掩碼到按字典順序排列下一個排列是一個不錯的bithack,這意味着遍歷所有設置了k位的掩碼非常簡單。 將這些蒙版與初始值進行XOR運算,可以得到所有漢明距離與漢明正好相距k的值。

因此,對於D尺寸,其中D小於32(否則請更改類型),

uint32_t limit = (1u << D) - 1;
for (int k = 1; k <= r; k++) {
    uint32_t diff = (1u << k) - 1;
    while (diff <= limit) {
        // v is the input vertex
        uint32_t vertex = v ^ diff;
        // use it
        diff = nextBitPermutation(diff);
    }
}

在哪里nextBitPermutation可以在C ++中實現為類似(如果您擁有__builtin_ctz

uint32_t nextBitPermutation(uint32_t v) {
    // see https://graphics.stanford.edu/~seander/bithacks.html#NextBitPermutation
    uint32_t t = v | (v - 1);
    return (t + 1) | (((~t & -~t) - 1) >> (__builtin_ctz(v) + 1));
}

或用於MSVC(未經測試)

uint32_t nextBitPermutation(uint32_t v) {
    // see https://graphics.stanford.edu/~seander/bithacks.html#NextBitPermutation
    uint32_t t = v | (v - 1);
    unsigned long tzc;
    _BitScanForward(&tzc, v); // v != 0 so the return value doesn't matter
    return (t + 1) | (((~t & -~t) - 1) >> (tzc + 1));
}

如果D 真的很低, popcntpshufb 4,則舊的popcnt -with- pshufb效果很好,通常一切都排列良好,如下所示:

uint16_t query(int vertex, int r, int8_t* validmask)
{
    // validmask should be array of 16 int8_t's,
    // 0 for a vertex that doesn't exist, -1 if it does
    __m128i valid = _mm_loadu_si128((__m128i*)validmask);
    __m128i t0 = _mm_set1_epi8(vertex);
    __m128i r0 = _mm_set1_epi8(r + 1);
    __m128i all =        _mm_setr_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
    __m128i popcnt_lut = _mm_setr_epi8(0, 1, 1, 2, 1, 2, 2, 3, 1, 2,  2,  3,  2,  3,  3,  4);
    __m128i dist = _mm_shuffle_epi8(popcnt_lut, _mm_xor_si128(t0, all));
    __m128i close_enough = _mm_cmpgt_epi8(r0, dist);
    __m128i result = _mm_and_si128(close_enough, valid);
    return _mm_movemask_epi8(result);
}

這應該相當快; 與上面的bithack相比,速度要快( nextBitPermutation相當重,在那里經常使用),並且與循環遍歷所有頂點並測試它們是否在范圍內(即使使用內置popcntpopcnt自動花費至少16個周期,並且假設所有內容均已緩存,甚至永久保存在寄存器中,則上述內容不應該)。 不利的一面是令人討厭的結果,因為它掩蓋了既存在又在查詢點范圍內的頂點,而不是它們的列表。 不過,它將與對與點關聯的數據進行一些處理很好地結合在一起。

當然,這也將縮小到D = 3,僅使> = 8的點都不有效。 D> 4可以類似地完成,但是它需要花費更多的代碼,並且由於這確實是一種蠻力解決方案,僅由於並行性而很快,因此從根本上講,它在D中的性能成指數地降低。

暫無
暫無

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

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