使用 AVX-512 的两个集合的 SIMD 矢量交集:需要加速

问题描述

我目前需要将两个已排序的向量相交。

这是我的实现:

#include <immintrin.h>
#include <stdint.h>

#include <algorithm>
#include <bit>
#include <chrono>
#include <cstring>
#include <iostream>
#include <string>
#include <vector>

using namespace std;

// Type your code here,or load an example.
void square(vector<uint64_t> &res,vector<uint64_t> &a,vector<uint64_t> &b) {
  set_intersection(a.begin(),a.end(),b.begin(),b.end(),back_inserter(res));
}

void super(vector<uint64_t> &res,vector<uint64_t> &b) {
  uint32_t offset = 0;

  for (auto it = a.begin(),it_end = a.end(); it != it_end; ++it) {
    auto r = _mm512_set1_epi64((uint64_t)*it);

    for (auto it2 = b.begin(),it2_end = b.end(); it2 != it2_end; it2 += 8) {
      auto distance = it2 - b.begin();
      auto *ptr = b.data() + distance;

      auto s = _mm512_loadu_epi64((const void *)ptr);

      auto m = _mm512_cmpeq_epu64_mask(r,s);

      auto count = popcount(m);

      auto *ptr2 = &(*(res.begin() + offset));

      _mm512_mask_compressstoreu_epi64((void *)ptr2,m,s);

      offset += count;
    }
  }

  // res.resize(offset);
}

int main() {
  vector<uint64_t> a,b;

  for (uint32_t x = 0; x < (64 * 1024); ++x) {
    a.push_back(x);
    b.push_back(x + 21);
  }
  vector<uint64_t> res(66000);

  for (uint32_t t = 0; t < 10; ++t) {
    auto c = std::chrono::high_resolution_clock::now();
    super(res,a,b);
    auto c2 = std::chrono::high_resolution_clock::now();
    auto d = chrono::duration_cast<chrono::nanoseconds>(c2 - c);

    cout << d.count() << endl;

    for (uint32_t x = 0,xs = 4; x < xs; ++x) {
      cout << res[x] << endl;
    }

    res.clear();
  }

  cout << "-------" << endl;

  for (uint32_t t = 0; t < 10; ++t) {
    auto c = std::chrono::high_resolution_clock::now();
    square(res,b);
    auto c2 = std::chrono::high_resolution_clock::now();
    auto d = chrono::duration_cast<chrono::nanoseconds>(c2 - c);

    cout << d.count() << endl;
    for (uint32_t x = 0,xs = 4; x < xs; ++x) {
      cout << res[x] << endl;
    }
    res.clear();
  }
}

我创建了一个 Godbolt 编译器示例来简化社区的测试: Godbolt's test box

我担心的是 SIMD 版本的糟糕性能,即使使用 AVX 指令(巨大的延迟)。

结果是正确的。

有人可以提供快速提示吗?

编辑:对于这个测试用例,我将向量设为 8 的倍数,所以不要打扰检查。

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)