问题描述
我目前需要将两个已排序的向量相交。
这是我的实现:
#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 (将#修改为@)