说明
实现base16编码,二进制转换为字符串,
原来数据一个字节有8位,经过base16编码后拆分为两个4位字节(最大值16),所以实现base16转码后数据量会扩大一倍,拆分后的字节映射到0123456789abcdef
单线程Base16编码
#include <iostream>
#include <thread>
#include <string>
#include <vector>
#include <chrono>
using namespace std;
using namespace chrono;
// base16对应的映射表
static const char base16[] = "0123456789abcdef";
void Base16Encode(const unsigned char* data, int size, unsigned char* out)
{
for (int i = 0; i < size; i++)
{
unsigned char d = data[i];
char a = base16[d >> 4]; // 通过右移获取高4位
char b = base16[d & 0x0F]; // 与0x0F进行与操作,获得低4位
out[i * 2] = a;
out[i * 2 + 1] = b;
}
}
int main()
{
string data = "base16编码测试";
unsigned char out[1024] = { 0 };
Base16Encode((unsigned char*)data.c_str(), data.size(), out);
// 测试单线程base16编码效率
{
// 初始化测试数据
vector<unsigned char> in_data;
in_data.resize(1024 * 1024 * 10);
for (int i = 0; i < in_data.size(); i++)
{
in_data[i] = i % 256;
}
vector<unsigned char> out_data;
out_data.resize(in_data.size() * 2); // base16编码,需要扩大两倍
auto start = system_clock::now(); //记录开始时间
Base16Encode(in_data.data(), in_data.size(), out_data.data());
auto end = system_clock::now(); //记录结束时间
auto duration = duration_cast<milliseconds>(end - start); // 单位为毫秒
cout << "单线程执行时间为:" << duration.count() << "毫秒" << endl;
}
std::cout << out << "Hello World!\n";
}
单线程执行结果
可以看到单线程执行所消耗的时间为34毫秒
多线程测试
#include <iostream>
#include <thread>
#include <string>
#include <vector>
#include <chrono>
using namespace std;
using namespace chrono;
// base16对应的映射表
static const char base16[] = "0123456789abcdef";
void Base16Encode(const unsigned char* data, int size, unsigned char* out)
{
for (int i = 0; i < size; i++)
{
unsigned char d = data[i];
char a = base16[d >> 4]; // 通过右移获取高4位
char b = base16[d & 0x0F]; // 与0x0F进行与操作,获得低4位
out[i * 2] = a;
out[i * 2 + 1] = b;
}
}
void Base16EncodeThread(const vector<unsigned char> &data, vector<unsigned char> &out)
{
int size = data.size();
int th_count = thread::hardware_concurrency(); // CPU硬件支持的核心数
// 切片数据
int slice_count = size / th_count; // 余数丢弃了
// 如果数据量小的话只切一片
if (size < th_count)
{
th_count = 1;
slice_count = size;
}
// 使用vector存放线程
vector<thread> ths;
ths.resize(th_count);
// 任务分配到各个线程
for (int i = 0; i < th_count; i++)
{
int offset = i * slice_count;
int count = slice_count;
// 最后一个线程会多处理一些数据
if (th_count > 1 && i == th_count - 1)
{
count = slice_count + size % th_count;
}
ths[i] = thread(Base16Encode, data.data() + offset, count, out.data());
}
// 等待所有线程处理结束
for(auto&th : ths)
{
th.join();
}
}
int main()
{
string data = "base16编码测试";
unsigned char out[1024] = { 0 };
Base16Encode((unsigned char*)data.c_str(), data.size(), out);
// 测试多线程base16编码效率
{
// 初始化测试数据
vector<unsigned char> in_data;
in_data.resize(1024 * 1024 * 10);
for (int i = 0; i < in_data.size(); i++)
{
in_data[i] = i % 256;
}
vector<unsigned char> out_data;
out_data.resize(in_data.size() * 2); // base16编码,需要扩大两倍
auto start = system_clock::now(); //记录开始时间
Base16EncodeThread(in_data, out_data);
auto end = system_clock::now(); //记录结束时间
auto duration = duration_cast<milliseconds>(end - start); // 单位为毫秒
cout << "多线程执行时间为:" << duration.count() << "毫秒" << endl;
}
std::cout << out << "Hello World!\n";
}
多线程执行结果
可以看到多线程执行时间为11毫秒
C++17中多线程处理结果
#include <iostream>
#include <vector>
#include <chrono>
#include <execution> // C++17
using namespace std;
using namespace chrono;
// base16对应的映射表
static const char base16[] = "0123456789abcdef";
int main()
{
// C++17多线程base16编码效率
{
// 初始化测试数据
vector<unsigned char> in_data;
in_data.resize(1024 * 1024 * 10);
for (int i = 0; i < in_data.size(); i++)
{
in_data[i] = i % 256;
}
vector<unsigned char> out_data;
out_data.resize(in_data.size() * 2); // base16编码,需要扩大两倍
auto start = system_clock::now(); //记录开始时间
// C++17
std::for_each(std::execution::par, in_data.begin(), in_data.end(), [&](auto& d)
{
char a = base16[d >> 4]; // 通过右移获取高4位
char b = base16[d & 0x0F]; // 与0x0F进行与操作,获得低4位
int index = &d - in_data.data(); // 获得数据的位置
out_data[index * 2] = a;
out_data[index * 2 + 1] = b;
});
auto end = system_clock::now(); //记录结束时间
auto duration = duration_cast<milliseconds>(end - start); // 单位为毫秒
cout << "C++17多线程执行时间为:" << duration.count() << "毫秒" << endl;
}
}
测试结果
C++17方式耗时长的原因可能是lambda表达式,每个字节的处理都要进入一次lambda表达式,因此开销会比较大,也有可能是Debug模式占用时间较多