C++多线程-chap3 多线程异步和通信-2


这里,只是记录自己的学习笔记。

顺便和大家分享多线程的基础知识。然后从入门到实战。有代码。

知识点来源:

https://edu.51cto.com/course/26869.html


C++11 实现base16,并与单线程进行性能测试

  1 /*
  2 C++17 多核并行计算
  3 
  4 4.1 手动实现多核 base16编码
  5 4.1.1 实现base16编码
  6   1.二进制转换为字符串
  7   2.一个字节8位,拆分为2个4位字节(最大值为16)
  8   3.拆分后的字节映射到 0123456789abcdef
  9 
 10 //不创建线程的情况下通过 foreach 实现多核编码
 11 
 12 */
 13 
 14 
 15 #include 
 16 #include 
 17 #include 
 18 #include 
 19 #include 
 20 using namespace std;
 21 
 22 static const char base16[] = "0123456789abcdef";
 23 
 24 //base16编码
 25 void Base16Encode(const unsigned char* data, int size, unsigned char* out)
 26 {
 27     for (int i = 0; i < size; i++) {
 28         unsigned char d = data[i];
 29         //1234 5678 >>4  0000 1234   ,右移4位,取到高位字节
 30         //1234 5678 & 0000 1111   0000 5678,与操作得到低位字节
 31         char a = base16[d >> 4];
 32         char b = base16[d & 0x0F];
 33         out[i * 2] = a;
 34         out[i * 2 + 1] = b;
 35     }
 36 }
 37 
 38 //C++11 多核base16编码
 39 void Base16EncodeThread(const vectorchar>& data, vectorchar> &out)
 40 {
 41     int size = data.size();
 42     int th_count = thread::hardware_concurrency();//系统支持的线程核心数
 43 
 44     //切片数据
 45     int slice_count = size / th_count;//余数丢弃
 46     if (size < th_count) { //只切一片
 47         th_count = 1;
 48         slice_count = size;
 49     }
 50 
 51     //准备好线程
 52     vector ths;
 53     ths.resize(th_count);
 54 
 55     //任务分配到各个线程
 56     for (int i = 0; i < th_count; i++) {
 57         // 1234 5678 9abc defg hi
 58         int offset = i * slice_count;
 59         int count = slice_count;
 60 
 61         //最后一个线程
 62         if (th_count > 1 && i == th_count - 1) {
 63             count = slice_count + size % th_count;
 64         }
 65         cout << "offset:" << offset << ",count:" << count << endl;
 66 
 67         ths[i] = thread(Base16Encode, data.data() + offset, count, out.data());
 68     }
 69 
 70     for (auto& th : ths) {
 71         th.join();//等待所有线程结束
 72     }
 73     cout << "over" << endl;
 74 }
 75 
 76 
 77 int main()
 78 {
 79     string test_data = "测试base16编码";
 80     unsigned char out[1024] = { 0 };
 81     Base16Encode((const unsigned char*)test_data.data(), test_data.size(), out);
 82     cout << "base16 Encode:" << out << endl;
 83     cout << "char length:" << sizeof(out) / sizeof(unsigned char) << endl;
 84 
 85     vectorchar> in_data;
 86     in_data.resize(1024 * 1024 * 20);//20M
 87     for (int i = 0; i < in_data.size(); i++) {
 88         in_data[i] = i % 256;
 89     }
 90     vectorchar> out_data;
 91     out_data.resize(in_data.size() * 2);
 92 
 93 
 94     //测试单线程 base16 编码效率
 95     {
 96         cout << "单线程 base16  开始计算" << endl;
 97 
 98         auto start = chrono::system_clock::now();
 99         Base16Encode(in_data.data(), in_data.size(), out_data.data());
100 
101         auto end = chrono::system_clock::now();
102         auto duration = chrono::duration_cast(end - start);
103         cout << "编码:"<"字节数据花费 " << duration.count() <<" 毫秒"< endl;
104         //cout << "out_data.data():" << out_data.data() << endl;
105     }
106 
107 
108     //C++11 多线程Base16编码
109     {
110         cout << "C++11 多线程Base16编码 开始计算" << endl;
111         auto start = chrono::system_clock::now();
112         Base16EncodeThread(in_data, out_data);
113         auto end = chrono::system_clock::now();
114         auto duration = chrono::duration_cast(end - start);
115         cout << "编码:" << in_data.size() << "字节数据花费 " << duration.count() << " 毫秒" << flush << endl;
116     }
117 
118 
119     //C++17   for_each 写法更加简洁
120     {
121         cout << "C++17 多线程Base16编码 开始计算" << endl;
122         auto start = chrono::system_clock::now();
123 
124         // #include  C++17支持
125         unsigned char* idata = in_data.data();
126         unsigned char* odata = out_data.data();
127 
128         //在release模式下,C++17会更快
129         std::for_each(std::execution::par,//并行计算 多核
130             in_data.begin(), in_data.end(),
131             [&](auto& d) { //多线程进入此函数
132             char a = base16[(d >> 4)];
133             char b = base16[(d & 0x0F)];
134             int index = &d - idata ;//计算偏移位置
135             odata[index * 2] = a;
136             odata[index * 2 + 1] = b;
137         }
138         );
139         
140         auto end = chrono::system_clock::now();
141         auto duration = chrono::duration_cast(end - start);
142         cout << "编码:" << in_data.size() << "字节数据花费 " << duration.count() << " 毫秒" << flush << endl;
143     }
144 
145 
146 
147     getchar();
148     return 0;
149 }