单线程、SSE、AVX运行效率对比

测试硬件:CPU-i5-4590
命令行:/arch:AVX
优化项:/O2

main.cpp

#include <iostream>
#include <vector>
#include "method.h"
#include <random>
#include <time.h>

using std::default_random_engine;
using std::uniform_real_distribution;

int main(int argc, char* argv[])
{
	//乘法累加运算
	{
		int size = 33;
		float *input1 = (float *)malloc(sizeof(float) * size);
		float *input2 = (float *)malloc(sizeof(float) * size);

		default_random_engine e;
		uniform_real_distribution<float> u(0, 1); //随机数分布对象 
		for (int i = 0; i < size; i++)
		{
			input1[i] = u(e);
			input2[i] = u(e);
		}

		int cntLoop = 10000000;

		clock_t start_t = clock();
		float org = 0.0;
		for (int i = 0; i < cntLoop; i++)
			org = MathMulAdd(input1, input2, size);
		printf("org = %f\t", org);
		printf("cost time: %d(ms)\n", clock() - start_t);

		start_t = clock();
		float sse = 0.0;
		for (int i = 0; i < cntLoop; i++)
			sse = SSEMulAdd(input1, input2, size);
		printf("sse = %f\t", sse);
		printf("cost time: %d(ms)\n", clock() - start_t);

		start_t = clock();
		float sse_ = 0.0;
		for (int i = 0; i < cntLoop; i++)
			sse_ = SSEFmAdd(input1, input2, size);
		printf("sse_= %f\t", sse_);
		printf("cost time: %d(ms)\n", clock() - start_t);

		start_t = clock();
		float avx = 0.0;
		for (int i = 0; i < cntLoop; i++)
			avx = AVXMulAdd(input1, input2, size);
		printf("avx = %f\t", avx);
		printf("cost time: %d(ms)\n", clock() - start_t);

		start_t = clock();
		float avx_ = 0.0;
		for (int i = 0; i < cntLoop; i++)
			avx_ = AVXFmAdd(input1, input2, size);
		printf("avx_= %f\t", avx_);
		printf("cost time: %d(ms)\n", clock() - start_t);

		free(input1);
		free(input2);
	}
	//结果:
	//org = 11.216135 cost time : 174(ms)
	//sse = 11.216136 cost time : 102(ms)
	//sse_ = 11.216136 cost time : 119(ms)
	//avx = 11.216136 cost time : 63(ms)
	//avx_ = 11.216136 cost time : 61(ms)


	//加法运算
	//{
	//	int size = 27;
	//	float *input = (float *)malloc(sizeof(float) * size);
	//	for (int i = 0; i < size; i++)
	//		input[i] = 0.0025;

	//	int cntLoop = 300000000;
	//	clock_t start_t = clock();
	//	float org = 0.0;
	//	for (int i = 0; i < cntLoop; i++)
	//		org = MathSum(input, size);
	//	printf("org = %f\t", org);
	//	printf("cost time: %d\n", clock() - start_t);

	//	start_t = clock();
	//	float sse = 0.0;
	//	for (int i = 0; i < cntLoop; i++)
	//		sse = SSESum(input, size);
	//	printf("sse = %f\t", sse);
	//	printf("cost time: %d\n", clock() - start_t);

	//	start_t = clock();
	//	float avx = 0.0;
	//	for (int i = 0; i < cntLoop; i++)
	//		avx = AVXSum(input, size);
	//	printf("avx = %f\t", avx);
	//	printf("cost time: %d\n", clock() - start_t);

	//	free(input);
	//}
	//结果:
	//org = 0.067500  cost time : 3062
	//sse = 0.067500  cost time : 2283
	//avx = 0.067500  cost time : 1829


	//最大值/最小值运算
	//{
	//	int size = 58;
	//	float *input = (float *)malloc(sizeof(float) * size);

	//	default_random_engine e;
	//	uniform_real_distribution<float> u(0, 3); //随机数分布对象 
	//	for (int i = 0; i < size; i++)
	//	{
	//		input[i] = u(e);
	//		printf("%f ", input[i]);
	//		if ((i + 1) % 8 == 0)
	//			printf("\n");
	//	}
	//	printf("\n");

	//	int cntLoop = 100000000;
	//	clock_t start_t = clock();
	//	float org;
	//	for (int i = 0; i < cntLoop; i++)
	//		org = MathMax(input, size);
	//	printf("org = %f\t", org);
	//	printf("cost time: %d(ms)\n", clock() - start_t);

	//	start_t = clock();
	//	float sse;
	//	for (int i = 0; i < cntLoop; i++)
	//		sse = SSEMax(input, size);
	//	printf("sse = %f\t", sse);
	//	printf("cost time: %d(ms)\n", clock() - start_t);

	//	start_t = clock();
	//	float avx;
	//	for (int i = 0; i < cntLoop; i++)
	//		avx = AVXMax(input, size);
	//	printf("avx = %f\t", avx);
	//	printf("cost time: %d(ms)\n", clock() - start_t);

	//	free(input);
	//}
	//结果:
	//org = 2.989384  cost time : 9491(ms)
	//sse = 2.989384  cost time : 1261(ms)
	//avx = 2.989384  cost time : 1413(ms)


	return 0;
}

method.h

#pragma once

#include <intrin.h>
#include <stdio.h>

float MathMulAdd(const float *input1, const float *input2, int size);
float SSEMulAdd(const float *input1, const float *input2, int size);
float SSEFmAdd(const float *input1, const float *input2, int size);
float AVXMulAdd(const float *input1, const float *input2, int size);
float AVXFmAdd(const float *input1, const float *input2, int size);


float MathSum(const float *input, int size);
float SSESum(const float *input, int size);
float AVXSum(const float *input, int size);


float MathMax(const float *input, int size);
float SSEMax(const float *input, int size);
float AVXMax(const float *input, int size);

method.cpp

#include "method.h"


float MathMulAdd(const float *input1, const float *input2, int size)
{
	float output = 0.0;
	for (int i = 0; i < size; i++)
	{
		output += input1[i] * input2[i];
	}
	return output;
}

float SSEMulAdd(const float *input1, const float *input2, int size)
{
	if (input1 == nullptr || input2 == nullptr)
	{
		printf("input data is null\n");
		return -1;
	}
	int nBlockWidth = 4;
	int cntBlock = size / nBlockWidth;
	int cntRem = size % nBlockWidth;

	float output = 0;
	__m128 loadData1, loadData2;
	__m128 mulData = _mm_setzero_ps();
	__m128 sumData = _mm_setzero_ps();
	const float *p1 = input1;
	const float *p2 = input2;
	for (int i = 0; i < cntBlock; i++)
	{
		loadData1 = _mm_load_ps(p1);
		loadData2 = _mm_load_ps(p2);
		mulData = _mm_mul_ps(loadData1, loadData2);
		sumData = _mm_add_ps(sumData, mulData);
		p1 += nBlockWidth;
		p2 += nBlockWidth;
	}
	sumData = _mm_hadd_ps(sumData, sumData); // p[0] + p[1] + p[4] + p[5] + ...
	sumData = _mm_hadd_ps(sumData, sumData); // p[2] + p[3] + p[6] + p[7] + ...
	output += sumData.m128_f32[(0)];         // 前4组

	for (int i = 0; i < cntRem; i++)
	{
		output += p1[i] * p2[i];
	}

	return output;
}

float SSEFmAdd(const float *input1, const float *input2, int size)
{
	if (input1 == nullptr || input2 == nullptr)
	{
		printf("input data is null\n");
		return -1;
	}
	int nBlockWidth = 4;
	int cntBlock = size / nBlockWidth;
	int cntRem = size % nBlockWidth;

	float output = 0;
	__m128 loadData1, loadData2;
	__m128 sumData = _mm_setzero_ps();
	const float *p1 = input1;
	const float *p2 = input2;
	for (int i = 0; i < cntBlock; i++)
	{
		loadData1 = _mm_load_ps(p1);
		loadData2 = _mm_load_ps(p2);
		sumData = _mm_fmadd_ps(loadData1, loadData2, sumData);
		p1 += nBlockWidth;
		p2 += nBlockWidth;
	}
	sumData = _mm_hadd_ps(sumData, sumData); // p[0] + p[1] + p[4] + p[5] + ...
	sumData = _mm_hadd_ps(sumData, sumData); // p[2] + p[3] + p[6] + p[7] + ...
	output += sumData.m128_f32[(0)];         // 前4组

	for (int i = 0; i < cntRem; i++)
	{
		output += p1[i] * p2[i];
	}

	return output;
}

float AVXMulAdd(const float *input1, const float *input2, int size)
{
	if (input1 == nullptr || input2 == nullptr)
	{
		printf("input data is null\n");
		return -1;
	}
	int nBlockWidth = 8;
	int cntBlock = size / nBlockWidth;
	int cntRem = size % nBlockWidth;

	float output = 0;
	__m256 loadData1, loadData2;
	__m256 mulData = _mm256_setzero_ps();
	__m256 sumData = _mm256_setzero_ps();
	const float *p1 = input1;
	const float *p2 = input2;
	for (int i = 0; i < cntBlock; i++)
	{
		loadData1 = _mm256_load_ps(p1);
		loadData2 = _mm256_load_ps(p2);
		mulData = _mm256_mul_ps(loadData1, loadData2);
		sumData = _mm256_add_ps(sumData, mulData);
		p1 += nBlockWidth;
		p2 += nBlockWidth;
	}
	sumData = _mm256_hadd_ps(sumData, sumData); // p[0] + p[1] + p[4] + p[5] + p[8] + p[9] + p[12] + p[13] + ... 
	sumData = _mm256_hadd_ps(sumData, sumData); // p[2] + p[3] + p[6] + p[7] + p[10] + p[11] + p[14] + p[15] + ... 
	output += sumData.m256_f32[(0)];            // 前4组
	output += sumData.m256_f32[(4)];            // 后4组

	for (int i = 0; i < cntRem; i++)
	{
		output += p1[i] * p2[i];
	}

	return output;
}

float AVXFmAdd(const float *input1, const float *input2, int size)
{
	if (input1 == nullptr || input2 == nullptr)
	{
		printf("input data is null\n");
		return -1;
	}
	int nBlockWidth = 8;
	int cntBlock = size / nBlockWidth;
	int cntRem = size % nBlockWidth;

	float output = 0;
	__m256 loadData1, loadData2;
	__m256 sumData = _mm256_setzero_ps();
	const float *p1 = input1;
	const float *p2 = input2;
	for (int i = 0; i < cntBlock; i++)
	{
		loadData1 = _mm256_load_ps(p1);
		loadData2 = _mm256_load_ps(p2);
		sumData = _mm256_fmadd_ps(loadData1, loadData2, sumData);
		p1 += nBlockWidth;
		p2 += nBlockWidth;
	}
	sumData = _mm256_hadd_ps(sumData, sumData); // p[0] + p[1] + p[4] + p[5] + p[8] + p[9] + p[12] + p[13] + ... 
	sumData = _mm256_hadd_ps(sumData, sumData); // p[2] + p[3] + p[6] + p[7] + p[10] + p[11] + p[14] + p[15] + ... 
	output += sumData.m256_f32[(0)];            // 前4组
	output += sumData.m256_f32[(4)];            // 后4组

	for (int i = 0; i < cntRem; i++)
	{
		output += p1[i] * p2[i];
	}

	return output;
}



float MathSum(const float *input, int size)
{
	float output = 0.0;
	for (int i = 0; i < size; i++)
	{
		output += input[i];
	}
	return output;
}

float SSESum(const float *input, int size)
{
	if (input == nullptr)
	{
		printf("input data is null\n");
		return -1;
	}
	int nBlockWidth = 4;
	int cntBlock = size / nBlockWidth;
	int cntRem = size % nBlockWidth;

	float output = 0;
	__m128 loadData;
	__m128 sumData = _mm_setzero_ps();
	const float *p = input;
	for (int i = 0; i < cntBlock; i++)
	{
		loadData = _mm_load_ps(p);
		sumData = _mm_add_ps(sumData, loadData);
		p += nBlockWidth;
	}
	sumData = _mm_hadd_ps(sumData, sumData); // p[0] + p[1] + p[4] + p[5] + ...
	sumData = _mm_hadd_ps(sumData, sumData); // p[2] + p[3] + p[6] + p[7] + ...
	output += sumData.m128_f32[(0)];         // 前4组

	for (int i = 0; i < cntRem; i++)
	{
		output += p[i];
	}

	return output;
}

float AVXSum(const float *input, int size)
{
	if (input == nullptr)
	{
		printf("input data is null\n");
		return -1;
	}
	int nBlockWidth = 8;
	int cntBlock = size / nBlockWidth;
	int cntRem = size % nBlockWidth;

	float output = 0;
	__m256 loadData;
	__m256 sumData = _mm256_setzero_ps();
	const float *p = input;
	for (int i = 0; i < cntBlock; i++)
	{
		loadData = _mm256_load_ps(p);
		sumData = _mm256_add_ps(sumData, loadData);
		p += nBlockWidth;
	}
	sumData = _mm256_hadd_ps(sumData, sumData); // p[0] + p[1] + p[4] + p[5] + p[8] + p[9] + p[12] + p[13] + ... 
	sumData = _mm256_hadd_ps(sumData, sumData); // p[2] + p[3] + p[6] + p[7] + p[10] + p[11] + p[14] + p[15] + ... 
	output += sumData.m256_f32[(0)];            // 前4组
	output += sumData.m256_f32[(4)];            // 后4组

	for (int i = 0; i < cntRem; i++)
	{
		output += p[i];
	}

	return output;
}


float MathMax(const float *input, int size)
{
	float maxVal = input[0];
	for (int i = 1; i < size; i++)
	{
		maxVal = maxVal > input[i] ? maxVal : input[i];
	}

	return maxVal;
}

float SSEMax(const float *input, int size)
{
	if (input == nullptr)
	{
		printf("input data is null\n");
		return -1;
	}
	int nBlockWidth = 4;
	int cntBlock = size / nBlockWidth;
	int cntRem = size % nBlockWidth;

	__declspec(align(16)) float output[4];
	__m128 loadData;
	const float *p = input;

	__m128 maxVal = _mm_load_ps(p);
	p += nBlockWidth;

	for (int i = 1; i < cntBlock; i++)
	{
		loadData = _mm_load_ps(p);
		maxVal = _mm_max_ps(maxVal, loadData);

		p += nBlockWidth;
	}
	_mm_store_ps(output, maxVal);

	float maxVal_ = output[0];
	for (int i = 1; i < 4; i++)
	{
		maxVal_ = maxVal_ > output[i] ? maxVal_ : output[i];
	}
	for (int i = 0; i < cntRem; i++)
	{
		maxVal_ = maxVal_ > p[i] ? maxVal_ : p[i];
	}

	return maxVal_;
}

float AVXMax(const float *input, int size)
{
	if (input == nullptr)
	{
		printf("input data is null\n");
		return -1;
	}
	int nBlockWidth = 8;
	int cntBlock = size / nBlockWidth;
	int cntRem = size % nBlockWidth;

	__declspec(align(32)) float output[8];
	__m256 loadData;
	const float *p = input;

	__m256 maxVal = _mm256_load_ps(p);
	p += nBlockWidth;

	for (int i = 1; i < cntBlock; i++)
	{
		loadData = _mm256_load_ps(p);
		maxVal = _mm256_max_ps(maxVal, loadData);

		p += nBlockWidth;
	}
	_mm256_store_ps(output, maxVal);

	float maxVal_ = output[0];
	for (int i = 1; i < 8; i++)
	{
		maxVal_ = maxVal_ > output[i] ? maxVal_ : output[i];
	}
	for (int i = 0; i < cntRem; i++)
	{
		maxVal_ = maxVal_ > p[i] ? maxVal_ : p[i];
	}

	return maxVal_;
}

gcc utf16 to utf32

int is_surrogate(char16_t uc) { return (uc - 0xd800u) < 2048u; }
int is_high_surrogate(char16_t uc) { return (uc & 0xfffffc00) == 0xd800; }
int is_low_surrogate(char16_t uc) { return (uc & 0xfffffc00) == 0xdc00; }
wchar_t surrogate_to_utf32(char16_t high, char16_t low) {
	return (high << 10) + low - 0x35fdc00;
}
void convert_utf16_to_utf32(const char16_t *input,
	size_t input_size,
	wchar_t *output)
{
	const char16_t * const end = input + input_size;
	while (input < end) {
		const char16_t uc = *input++;
		if (!is_surrogate(uc)) {
			*output++ = uc;
		}
		else {
			if (is_high_surrogate(uc) && input < end && is_low_surrogate(*input))
				*output++ = surrogate_to_utf32(uc, *input++);
			else {
				// ERROR
			}
		}
	}
}

//utf32 to utf16
size_t utf32_to_utf16(wchar_t src, char16_t* des)
{
	if (src == 0) return 0;

	if (src <= 0xFFFF)
	{
		if (des) (*des) = static_cast(src);
		return 1;
	}
	else
		if (src <= 0xEFFFF)
		{
			if (des)
			{
				des[0] = static_cast(0xD800 + (src >> 10) - 0x40);  // high
				des[1] = static_cast(0xDC00 + (src & 0x03FF));      // low
			}
			return 2;
		}
	return 0;
}
const String& BinaryReader::ReadUnicode()
{
	static String str;
	int count = ReadInt32();

	if (count > 0)
	{
		static char buffer[512];
		stream.read(buffer, count);
#ifndef __BUILD_IN_MSYS2
		str.assign(reinterpret_cast(buffer), count / sizeof(wchar_t));
#else
		int iDstLength = count / 2;
		wchar_t *wchDst = new wchar_t[iDstLength + 1];
		memset(wchDst, 0, sizeof(wchar_t) * (iDstLength + 1));
		convert_utf16_to_utf32((const char16_t *)buffer, iDstLength, wchDst);
		str = wchDst;
		delete[] wchDst;
		if (str.length() > iDstLength) {
			str = str.substr(0, iDstLength);
		}

		//to utf16
		char16_t *u16Str = new char16_t[iDstLength + 1];
		memset(u16Str, 0, sizeof(char16_t) * (iDstLength + 1));
		for (int i = 0; i < str.length(); i++) {
			utf32_to_utf16(str[i], u16Str + i);
		}

		//to utf32
		wchar_t *wchDst2 = new wchar_t[iDstLength + 1];
		memset(wchDst2, 0, sizeof(wchar_t) * (iDstLength + 1));
		convert_utf16_to_utf32((const char16_t *)u16Str, iDstLength, wchDst2);
		
		delete [] wchDst2;
		delete [] u16Str;
#endif

		return str;
	}

	str = L"";
	return str;
}

CMakeList.txt Demo

动态库:

PROJECT(ProjectName)
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
#add_compile_definitions(BOOST_WINDOWS)
#add_compile_definitions(__BUILD_IN_MSYS2)
add_definitions(-D __BUILD_IN_MSYS2)
add_definitions(-D BOOST_LOG_DYN_LINK)
set(CMAKE_CXX_STANDARD 11) # C++11...
set(CMAKE_CXX_STANDARD_REQUIRED ON) #...is required...
SET(CMAKE_CXX_FLAGS "-std=c++11")
set(CMAKE_CXX_EXTENSIONS OFF) #...without compiler extensions like gnu++11
#set(HEADER_FILES /c/msys64/mingw64/x86_64-w64-mingw32/include/pthread.h)
#INCLUDE_DIRECTORIES("/c/msys64/mingw64/include")
#INCLUDE_DIRECTORIES("/d/code/ProjectName")
INCLUDE_DIRECTORIES("../Base")
INCLUDE_DIRECTORIES("/usr/include/mysql-cppconn/jdbc/")
#LINK_DIRECTORIES(/d/code/Base)
#LINK_DIRECTORIES(/c/msys64/mingw64/lib)
LINK_DIRECTORIES(../Image/Image)
LINK_DIRECTORIES(/usr/local/lib)
AUX_SOURCE_DIRECTORY(. DIR_SRCS)
AUX_SOURCE_DIRECTORY(../Base DIR_SRCS_BASE)
list(REMOVE_ITEM DIR_SRCS "Logger.h")
list(REMOVE_ITEM DIR_SRCS "Logger.cpp")
ADD_LIBRARY(ProjectName SHARED ${DIR_SRCS_BASE} ${DIR_SRCS_SCENE} ${DIR_SRCS_SCENE_DB} ${DIR_SRCS})
#TARGET_LINK_LIBRARIES(ProjectName Scene)
#TARGET_LINK_LIBRARIES(ProjectName Base)
TARGET_LINK_LIBRARIES(ProjectName Image)
TARGET_LINK_LIBRARIES(ProjectName boost_date_time)
TARGET_LINK_LIBRARIES(ProjectName boost_filesystem)
TARGET_LINK_LIBRARIES(ProjectName boost_iostreams)
TARGET_LINK_LIBRARIES(ProjectName boost_locale)
TARGET_LINK_LIBRARIES(ProjectName boost_log_setup)
TARGET_LINK_LIBRARIES(ProjectName boost_log)
TARGET_LINK_LIBRARIES(ProjectName boost_thread)
TARGET_LINK_LIBRARIES(ProjectName pthread)
TARGET_LINK_LIBRARIES(ProjectName z)
TARGET_LINK_LIBRARIES(ProjectName mysqlcppconn)
TARGET_LINK_LIBRARIES(ProjectName stdc++)

动态库:

PROJECT(Image)
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
add_definitions(-D __BUILD_IN_MSYS2)
#add_compile_definitions(BOOST_WINDOWS)
add_definitions(-D IMAGE_EXPORTS)
set(CMAKE_CXX_STANDARD 11) # C++11...
set(CMAKE_CXX_STANDARD_REQUIRED ON) #...is required...
set(CMAKE_CXX_EXTENSIONS OFF) #...without compiler extensions like gnu++11
SET(CMAKE_CXX_FLAGS "-std=c++0x")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC" )
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC" )
#set(HEADER_FILES /c/msys64/mingw64/x86_64-w64-mingw32/include/pthread.h)
#INCLUDE_DIRECTORIES("/c/msys64/mingw64/include")
INCLUDE_DIRECTORIES("/root/poco-poco-1.8.1-release/Foundation/include")
INCLUDE_DIRECTORIES("../jpeg")
INCLUDE_DIRECTORIES("../png")
INCLUDE_DIRECTORIES("../zlib")
INCLUDE_DIRECTORIES("../RectangleBinPack")
INCLUDE_DIRECTORIES("../CxImage")
LINK_DIRECTORIES(../CxImage)
LINK_DIRECTORIES(../jpeg)
LINK_DIRECTORIES(../png)
LINK_DIRECTORIES(../zlib)
LINK_DIRECTORIES(../RectangleBinPack)
#LINK_DIRECTORIES(/c/msys64/mingw64/lib)
AUX_SOURCE_DIRECTORY(. DIR_SRCS)
list(REMOVE_ITEM DIR_SRCS "Image.cpp")
ADD_LIBRARY(Image SHARED ${DIR_SRCS})
#set_property(TARGET Image PROPERTY POSITION_INDEPENDENT_CODE ON)
TARGET_LINK_LIBRARIES(Image CxImage)
TARGET_LINK_LIBRARIES(Image jpeg)
TARGET_LINK_LIBRARIES(Image png)
TARGET_LINK_LIBRARIES(Image zlib)
TARGET_LINK_LIBRARIES(Image RectangleBinPack)
TARGET_LINK_LIBRARIES(Image PocoFoundation)
TARGET_LINK_LIBRARIES(Image stdc++)

静态库:

PROJECT(CxImage)
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
add_definitions(-D __BUILD_IN_MSYS2)
set(CMAKE_CXX_STANDARD 11) # C++11...
set(CMAKE_CXX_STANDARD_REQUIRED ON) #...is required...
set(CMAKE_CXX_EXTENSIONS OFF) #...without compiler extensions like gnu++11
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC" )
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC" )
#set(HEADER_FILES /c/msys64/mingw64/x86_64-w64-mingw32/include/pthread.h)
#INCLUDE_DIRECTORIES("/c/msys64/mingw64/include")
AUX_SOURCE_DIRECTORY(. DIR_SRCS)
ADD_LIBRARY(CxImage STATIC ${DIR_SRCS})

可执行程序:

PROJECT(Test)
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
#add_compile_definitions(BOOST_WINDOWS)
#add_compile_definitions(__BUILD_IN_MSYS2)
add_definitions(-D __BUILD_IN_MSYS2)
add_definitions(-D BOOST_LOG_DYN_LINK)
set(CMAKE_CXX_STANDARD 11) # C++11...
set(CMAKE_CXX_STANDARD_REQUIRED ON) #...is required...
SET(CMAKE_CXX_FLAGS "-std=c++11")
set(CMAKE_CXX_EXTENSIONS OFF) #...without compiler extensions like gnu++11
#set(HEADER_FILES /c/msys64/mingw64/x86_64-w64-mingw32/include/pthread.h)
#INCLUDE_DIRECTORIES("/c/msys64/mingw64/include")
#INCLUDE_DIRECTORIES("../SceneBuilder")
#LINK_DIRECTORIES(/d/code/Base)
#LINK_DIRECTORIES(/d/code/Scene)
#LINK_DIRECTORIES(/c/msys64/mingw64/lib)
LINK_DIRECTORIES(../SceneBuilder)
LINK_DIRECTORIES(/usr/local/lib)
AUX_SOURCE_DIRECTORY(. DIR_SRCS)
add_executable(Test ${DIR_SRCS})
TARGET_LINK_LIBRARIES(Test SceneBuilder)
TARGET_LINK_LIBRARIES(Test boost_date_time)
TARGET_LINK_LIBRARIES(Test boost_filesystem)
TARGET_LINK_LIBRARIES(Test boost_iostreams)
TARGET_LINK_LIBRARIES(Test boost_locale)
TARGET_LINK_LIBRARIES(Test boost_log_setup)
TARGET_LINK_LIBRARIES(Test boost_log)
TARGET_LINK_LIBRARIES(Test boost_thread)
TARGET_LINK_LIBRARIES(Test pthread)
TARGET_LINK_LIBRARIES(Test stdc++)

编译:

cd /root/ProjectSrc
/usr/local/bin/cmake -DCMAKE_BUILD_TYPE=Release .
make

VS 2017 调试c++ dll的两种方式

环境状况:dll采用c++编写,宿主exe程序采用c#编写,两者不在同一解决方案中

方法一:手动附加
1、编译debug模式dll,放到exe所在目录
2、启动exe(非vs调试模式)
3、在dll项目中选择 调试-附加到进程,选中对应的exe进程,调试代码类型选择:本机。执行到dll调用时即可进入代码调试
  注:可以在exe的main函数中加入一段sleep以等待被附加

方法二:自动附加
1、编译debug模式dll,放到exe所在目录
2、打开dll项目属性,调试-命令,输入exe的完整路径,命令参数中填入exe所需的参数(要确保选项“附加”为否)
3、在dll项目上点击右键-调试-启动新实例,即可自动启动exe并附加到此进程

用VC和MinGW导出dll的def和lib(a)文件

有了dll文件需要导出def文件:
In msys2:
pacman -S mingw-w64-x86_64-tools
or x86:
pacman -S mingw-w64-i686-tools
gendef zlib1.dll
In MinGW:
pexports zlib1.dll > zlib1.def

有了dll和def文件,需要导出MinGW的.a文件:
dlltool --dllname zlib1.dll --def zlib1.def --output-lib libz.dll.a

有了dll和def文件,需要导出一个VC的lib文件:
运行VS开发人员命令提示符
lib /machine:X64 /def:zlib1.def
or x86:
lib /machine:i386 /def:zlib1.def

注意:
C++的dll不具有2进制级别的共享性,也就是说VC的MinGW的C++ dll不能混用。
而C的可以。
pexports和dlltool的MinGW的工具,lib是VC的工具。

树莓派更换中国大陆地区软件源(stretch)

查看自己的版本类型:
lsb_release -a

sudo nano /etc/apt/sources.list
将文件里的默认的官方软件源用# 注释掉
deb http://mirrors.ustc.edu.cn/raspbian/raspbian/ stretch main contrib non-free rpi

sudo nano /etc/apt/sources.list.d/raspi.list
将文件里的默认的官方软件源用# 注释掉
deb http://mirrors.tuna.tsinghua.edu.cn/raspberrypi stretch main ui

sudo apt-get update
sudo apt-get upgrade

CentOS 7 VMware 联网

dhclient –v
ip addr


Add this in auto-startup
cd /etc/init.d

vi net-autostart
#!/bin/bash
# Solution for "No Internet Connection from VMware"
#
### BEGIN INIT INFO
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
### END INIT INFO
dhclient -v


chmod 755 net-autostart
chkconfig --add net-autostart

restart vm to test

Linux下使用iptables禁止指定IP地址的网络连接

在Linux下,使用iptables来维护IP规则表。要封停或者是解封IP,其实就是在IP规则表添加规则。
要禁止指定IP地址的网络连接,可以使用以下两种方法来快速实现。

1.禁止特定IP的连接
要禁止一个IP,使用下面这条命令:
iptables -I INPUT -s ***.***.***.*** -j DROP
如果需要指定端口:
iptables -I INPUT -s ***.***.***.*** -ptcp --dport 22 -j DROP

要解封一个IP,使用下面这条命令:
iptables -D INPUT -s ***.***.***.*** -j DROP

参数-I是表示 Insert (添加),-D表示 Delete (删除)。后面跟的是规则, INPUT 表示入站,***.***.***.*** 表示要封停的IP, DROP 表示放弃连接。

service iptables save
service iptables restart

可以使用下面的命令来查看当前的IP规则表: 
iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination         
DROP       all  --  120.120.120.36       anywhere                      

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

如果输出非常慢,可使用:
iptables -n -L
-n选项,主机和端口都以数字形式输出,不会去查询主机名(DNS查询是比较慢的)


2. 禁止IP段的网络连接
添加IP段到封停列表中: 
iptables -I INPUT -s 121.0.0.0/8 -j DROP

CentOS 7 SSH使用证书登录

客户端建立私钥和公钥
在客户端终端运行命令
ssh-keygen -t rsa


ssh服务端配置
vi /etc/ssh/sshd_config
# 是否让 sshd 去检查用户家目录或相关档案的权限数据,
# 这是为了担心使用者将某些重要档案的权限设错,可能会导致一些问题所致。
# 例如使用者的 ~.ssh/ 权限设错时,某些特殊情况下会不许用户登入
StrictModes no
# 是否允许用户自行使用成对的密钥系统进行登入行为,仅针对 version 2。
# 至于自制的公钥数据就放置于用户家目录下的 .ssh/authorized_keys 内
RSAAuthentication yes
PubkeyAuthentication yes
AuthorizedKeysFile %h/.ssh/authorized_keys


把客户端的公钥添加到服务器的authorized_keys
vi ~/.ssh/id_rsa.pub
复制到服务器上的
/home/username/.ssh/authorized_keys
文件中


服务端重启sshd
systemctl restart sshd


客户端通过私钥登录ssh服务器
ssh -i ~/.ssh/id_rsa name@


每次敲命令,都要指定私钥,是一个很繁琐的事情,所以我们可以把私钥的路径加入ssh客户端的默认配置里
vi /etc/ssh/ssh_config
#其实默认id_rsa就已经加入私钥的路径了,这里只是示例而已
IdentityFile ~/.ssh/id_rsa
#如果有其他的私钥,还要再加入其他私钥的路径
IdentityFile ~/.ssh/blue_rsa