【发布时间】:2023-04-04 00:20:02
【问题描述】:
我得到一个小写字符数组(最大 1.5Gb)和一个字符 c。我想使用 AVX 指令找出字符 c 出现了多少次。
unsigned long long char_count_AVX2(char * vector, int size, char c){
unsigned long long sum =0;
int i, j;
const int con=3;
__m256i ans[con];
for(i=0; i<con; i++)
ans[i]=_mm256_setzero_si256();
__m256i Zer=_mm256_setzero_si256();
__m256i C=_mm256_set1_epi8(c);
__m256i Assos=_mm256_set1_epi8(0x01);
__m256i FF=_mm256_set1_epi8(0xFF);
__m256i shield=_mm256_set1_epi8(0xFF);
__m256i temp;
int couter=0;
for(i=0; i<size; i+=32){
couter++;
shield=_mm256_xor_si256(_mm256_cmpeq_epi8(ans[0], Zer), FF);
temp=_mm256_cmpeq_epi8(C, *((__m256i*)(vector+i)));
temp=_mm256_xor_si256(temp, FF);
temp=_mm256_add_epi8(temp, Assos);
ans[0]=_mm256_add_epi8(temp, ans[0]);
for(j=1; j<con; j++){
temp=_mm256_cmpeq_epi8(ans[j-1], Zer);
shield=_mm256_and_si256(shield, temp);
temp=_mm256_xor_si256(shield, FF);
temp=_mm256_add_epi8(temp, Assos);
ans[j]=_mm256_add_epi8(temp, ans[j]);
}
}
for(j=con-1; j>=0; j--){
sum<<=8;
unsigned char *ptr = (unsigned char*)&(ans[j]);
for(i=0; i<32; i++){
sum+=*(ptr+i);
}
}
return sum;
}
【问题讨论】:
-
你的字符格式是什么? ASCII 还是某种 Unicode?span>
-
格式为ASCII
-
AVX1 还是 AVX2?你试过什么?提示:检查
_mm256_cmpeq_epi8和_mm256_sub_epi8以获得最内部的循环。在 255 次迭代后,您需要开始将两个字节合并为一个uint16,依此类推 -
_mm256_cmpeq_epi8将在每个字节中为您提供-1。如果你从计数器中减去它(使用_mm256_sub_epi8),你可以直接数到 255 或 128,也就是说,你最内层的循环应该只包含这两个内在函数。 -
一个核心通常不能使 DRAM 带宽饱和,因此对于 large 输入,可能值得使用多个线程(特别是如果您已经启动了一个工作线程并且可以发送它是一个函数指针和参数)。你标记了这个parallel-processing,你是要OpenMP还是什么?
标签: c parallel-processing character intel simd