C++多线程-chap3 多线程异步和通信-2
这里,只是记录自己的学习笔记。
顺便和大家分享多线程的基础知识。然后从入门到实战。有代码。
知识点来源:
https://edu.51cto.com/course/26869.html
C++11 实现base16,并与单线程进行性能测试
base16编码,解码,请看这篇文章:https://www.cnblogs.com/music-liang/p/15656218.html
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 <iostream> 16 #include <thread> 17 #include <vector> 18 #include <chrono> 19 #include <execution> 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 vector<unsigned char>& data, vector<unsigned char> &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<thread> 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 vector<unsigned char> 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 vector<unsigned char> 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<chrono::milliseconds>(end - start); 103 cout << "编码:"<<in_data.size()<<"字节数据花费 " << duration.count() <<" 毫秒"<<flush<< 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<chrono::milliseconds>(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 <execution> 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<chrono::milliseconds>(end - start); 142 cout << "编码:" << in_data.size() << "字节数据花费 " << duration.count() << " 毫秒" << flush << endl; 143 } 144 145 146 147 getchar(); 148 return 0; 149 }