c++ SIMD AVX2比较 例子

c++ SIMD AVX2比较 例子示例代码含义:记目标字符串中有多少个目标字符。linux代码(例子)如下:#include<iostream>#include<x86intrin.h>#include<fstream>#include<chrono>usingnamespacestd;structStringView{constchar*p;constsize_tlen;};StringViewFileSize(const

大家好,又见面了,我是你们的朋友全栈君。

示例代码含义:记目标字符串中有多少个目标字符。
linux代码(例子)如下:

#include <iostream>
#include <x86intrin.h>
#include <fstream>
#include <chrono>

using namespace std;

struct StringView { 
   
    const char* p;
    const size_t len;
};

StringView FileSize(const char* fileName) { 
   
    ifstream ifstr(fileName);
    const auto b = ifstr.tellg();
    ifstr.seekg(0, ios::end);
    const auto e = ifstr.tellg();
    const size_t fileSize = e - b;
    ifstr.seekg(0, ios::beg);
    char *p = new char[fileSize];
    ifstr.read(p, fileSize);
    return { 
   p, fileSize};
}

// Normal function
size_t count_c_normal(const StringView& str, const uint8_t c) { 
   
    uint32_t num = 0;
    for (uint32_t i = 0; i < str.len; ++i) { 
   
        if (c == *(str.p + i)) { 
   
            ++num;
        }
    }
    return num;
}

// SIMD function
size_t count_c_simd(const StringView& str, const uint8_t c) { 
   
    __m128i ch = _mm_set1_epi8(c); // char ch[16] = { c, c, ..., c }
    size_t cnt = 0;
    uint32_t i = 0;
    for (; i < str.len; i+=16) { 
   
        // char t[16] = { (str+i)[0], (str+i)[1], ... }
        __m128i t = _mm_loadu_si128((__m128i *)(str.p + i));
        __m128i res = _mm_cmpeq_epi8(t, ch);

        // res[16] = { 0xFF, 0x00, 0xFF ... }
        unsigned mask = _mm_movemask_epi8(res);

        // bits[16] = 0...1101
        cnt += __builtin_popcount(mask);
    }

    // free cnt .
    for (; i < str.len; ++i) { 
   
        if (c == *(str.p + i))
        { 
   
            ++cnt;
        }
    }
    return cnt;
}

// AVX function
size_t count_c_avx256(const StringView& str, const uint8_t c) { 
   
    __m256i ch = _mm256_set1_epi8(c); // char ch[16] = { c, c, ..., c }
    size_t cnt = 0;
    uint32_t i = 0;
    for (; i < str.len; i+=32) { 
   
        // char t[16] = { (str+i)[0], (str+i)[1], ... }
        __m256i t = _mm256_loadu_si256((__m256i *)(str.p + i));
        __m256i res = _mm256_cmpeq_epi8(t, ch);

        // res[16] = { 0xFF, 0x00, 0xFF ... }
        unsigned mask = _mm256_movemask_epi8(res);

        // bits[16] = 0...1101
        cnt += __builtin_popcount(mask);
    }

    // free cnt .
    for (; i < str.len; ++i) { 
   
        if (c == *(str.p + i))
        { 
   
            ++cnt;
        }
    }
    return cnt;
}

int main() { 
   
    const auto ret = FileSize("./test_file");
    size_t cnt1 = 0, cnt2 = 0, cnt3 = 0;
    const auto t1 = std::chrono::steady_clock::now();
    cnt1 = count_c_normal(ret, uint8_t('1'));
    const auto t2 = std::chrono::steady_clock::now();
    cnt2 = count_c_simd(ret, uint8_t('1'));
    const auto t3 = std::chrono::steady_clock::now();
    cnt3 = count_c_avx256(ret, uint8_t('1'));
    const auto t4 = std::chrono::steady_clock::now();
    std::cout << "cnt1:" << cnt1 << ",cnt2:" << cnt2 << ",cnt3:" << cnt3 << std::endl;
    const auto d1 = std::chrono::duration_cast<std::chrono::milliseconds>(t2-t1).count();
    const auto d2 = std::chrono::duration_cast<std::chrono::milliseconds>(t3-t2).count();
    const auto d3 = std::chrono::duration_cast<std::chrono::milliseconds>(t4-t3).count();
    std::cout << "time1:" << d1 << ",time2:" << d2 << ",time3:" << d3 << std::endl;
    return 0;
}

生成随机文件代码详见:https://blog.csdn.net/weixin_41644391/article/details/113526563

编译命令:g++ -std=c++11 main.cc -o main -mavx -mavx2 -O2
性能:

普通O2:1890ms,simd:509ms,avx2:253ms

因为编译命令中加了avx2,怀疑simd的代码也被avx2优化了。纯simd结果可见:https://blog.csdn.net/weixin_41644391/article/details/113526563

其他:基于avx512的测试因为不支持gcc4.8.5,所以需要等一段时间才能出来。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/144029.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • fastclick

    fastclickfastclick–处理移动端click事件300毫秒延迟安装:npminstallfastclick–save   之后,在main.js中引入    importFastClickfrom’fastclick’    并绑定到bodyFastClick.attach(document.body);1、兼容性iOS3及更高版本的移动SafariiOS5及更高版本的C…

    2022年6月19日
    51
  • 动态获取地址×××解决方案

    动态获取地址×××解决方案

    2021年8月19日
    50
  • Git 指令集

    Git 指令集Git指令集Git是分散式的版本控制系統,從架設、簡易操作、設定,此篇主要是整理基本操作、遠端操作等.註:Git的範圍太廣了,把這篇當作是初學入門就好了.注意事項由project/.git/config可知:(若有更多,亦可由此得知)origin(remote)是Repository的版本master(branch)是

    2022年5月30日
    31
  • SpringBoot自动配置的原理及实现

    SpringBoot自动配置的原理及实现SpringBoot自动配置的实现原理SpringBoot的核心就是自动配置,自动配置又是基于条件判断来配置Bean。关于自动配置的源码在spring-boot-autoconfigure-2.0.3.RELEASE.jar回顾配置属性在通常需要我们在property中配置信息时,通常使用@ConfigurationProperties(pefix=“前缀”)注解的方式从配置文件中获取配置…

    2022年5月5日
    37
  • 如何做好Flex与Java交互「建议收藏」

    如何做好Flex与Java交互「建议收藏」三种flex4与Java顺利通信的方式是:flex与普通java类通信RemoteObject;flex与服务器交互HTTPService;flex与webservice交互WebService

    2022年7月2日
    18
  • kettle下载安装使用教程

    kettle下载安装使用教程Kettle简介Kettle是一款国外开源的ETL工具,纯java编写,可以在Window、Linux、Unix上运行, 数据抽取高效稳定。Kettle中文名称叫水壶,该项目的主程序员MATT希望把各种数据放到一个壶里,然后以一种指定的格式流出。Kettle这个ETL工具集,它允许你管理来自不同数据库的数据,通过提供一个图形化的用户环境来描述你想做什么,而不是你想怎么做。Kettle中有两…

    2022年5月24日
    28

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号