MMX及SSE优化--SSE篇

2023-11-08

 上回讲到针对整数运算的MMX优化技术,然而真正大运算量的图形和声音处理大都用的是浮点运算,而且现在对浮点运算的要求也是越来越高,在这样一个条件下INTEL终于在Pentium III处理中增加针对浮点运算优化的SSE指令,所以所有用过SSE指令的程序必须在Pentium III或者Althon XP以后的CPU上才来运行。

 SSE全新定义了8个新的128位寄存器xmm0-xmm7,比MMX的64位还提高了1倍,每个寄存器可以同时装入4个32位的浮点数,因为是全新的寄存器,所以少了MMX寄存器与原浮点寄存器的切换工作,所以有了更高的执行效率。值得注意的SSE还可以对16位和8位的整数进行运算,不过这已经不是SSE应用的主流了。

 在这里随便提一个Intel Compiler 8.0,这个编译器的优化能力的确是强,个人感觉大概比Visual C++ 6.0 SP6快10-20%左右,它可以针对不同的CPU作出优化,如果你是P4系列的cpu,在编译的时候加上参数/fast /QxW /Qip /Qunroll40,会有意想不到的结果,如果你再阅读一个它的用户手册,按照里面的方法稍微修改一下程序将会有更多提高,向所有崇拜极限优化的朋友推荐这款编译器。题外话少说,再次转入SSE正题,下面还是给出一个简单的例子:

在VC中使用内联汇编
float a[]={1.0,2.0,3.0,4.0};
float b[]={5.0,6.0,7.0,8.0};
_asm{
mov ecx,a;
mov edx,b;
movaps xmm0,[ecx];
movaps xmm1,[edx];
addps xmm0,xmm1;
movaps [ecx],xmm0;
}

跟MMX一样也可以不用汇编只用包含一个头文件就可以直接在C里面使用了:
#include
__m128 a = _mm_set_ps(1, 2, 3, 4)
__m128 b = _mm_set_ps(5, 6, 7, 8)
a = _mm_add_ps(a, b);
这个时候就感觉使用Intrinsics方便多了,因为它制定了好多合成的伪指令,方便了不少。

下面顺便贴一段SSE的部分指令介绍,更全的可以找Intel下载指令手册。下面这部分是引用至:
http://dwbclz.myetang.com/articles/piii/sse-ins-ref.html


ADDPS

格式:ADDPS xmm1, xmm2/m128

功能:两组单精度数相加

算法:

DEST[31-0] = DEST[31-0] + SRC/m128[31-0] ;
DEST[63-32] = DEST[63-32] + SRC/m128[63-32] ;
DEST[95-64] = DEST[95-64] + SRC/m128[95-64] ;
DEST[127-96] = DEST[127-96] + SRC/m128[127-96];

ADDSS

格式:ADDSS xmm1, xmm2/m32

功能:低位单精度数相加

算法:

DEST[31-0] = DEST[31-0] + SRC/m32[31-0];
DEST[63-32] = DEST[63-32] ;
DEST[95-64] = DEST[95-64] ;
DEST[127-96] = DEST[127-96];
 
ANDNPS

格式:ANDNPS xmm1, xmm2/m128

功能:xmm1“取反”再和 xmm2/m128 求“与”运算

算法:

DEST[127-0] = NOT (DEST[127-0]) AND SRC/m128[127-0];

ANDPS

格式:ANDPS xmm1, xmm2/m128

功能:进行两个寄存器的逻辑“与”操作

算法:

DEST[127-0] AND= SRC/m128[127-0];

CMPPS

格式:CMPPS xmm1, xmm2/m128, imm8

功能:比较两个寄存器的数值,根据imm8的不同数值采用不同的比较方法

imm8 == 0, ==; imm8 == 1, <; imm8 == 2, <=; imm8 == 3, ;
imm8 == 4, !=; imm8 == 5, !<; imm8 == 6, !<=; imm8 == 7, !;

算法:

IF (imm8 = 0) THEN
 OP = "EQ";
ELSEIF (imm8 = 1) THEN
 OP = "LT";
ELSEIF (imm8 = 2) THEN
 OP = "LE";
ELSEIF (imm8 = 3) THEN
 OP = "UNORD";
ELSEIF (imm8 = 4) THEN
 OP = "NE";
ELSEIF (imm8 = 5) THEN
 OP = "NLT";
ELSEIF (imm8 = 6) THEN
 OP = "NLE";
ELSEIF (imm8 = 7) THEN
 OP = "ORD";
FI

CMP0 = DEST[31-0] OP SRC/m128[31-0];
CMP1 = DEST[63-32] OP SRC/m128[63-32];
CMP2 = DEST [95-64] OP SRC/m128[95-64];
CMP3 = DEST[127-96] OP SRC/m128[127-96];

IF (CMP0 = TRUE) THEN
 DEST[31-0] = 0XFFFFFFFF;
ELSE
 DEST[31-0] = 0X00000000;
FI
IF (CMP1 = TRUE) THEN
 DEST[63-32] = 0XFFFFFFFF;
ELSE
 DEST[63-32] = 0X00000000;
FI
IF (CMP2 = TRUE) THEN
 DEST[95-64] = 0XFFFFFFFF;
ELSE
 DEST[95-64] = 0X00000000;
FI
IF (CMP3 = TRUE) THEN
 DEST[127-96] = 0XFFFFFFFF;
ELSE
 DEST[127-96] = 0X00000000;
FI

其它:你可以使用下面的可读性良好的指令

指令 实现
CMPEQPS xmm1, xmm2; CMPPS xmm1,xmm2, 0
CMPLTPS xmm1, xmm2; CMPPS xmm1,xmm2, 1
CMPLEPS xmm1, xmm2; CMPPS xmm1,xmm2, 2
CMPUNORDPS xmm1, xmm2; CMPPS xmm1,xmm2, 3
CMPNEQPS xmm1, xmm2; CMPPS xmm1,xmm2, 4
CMPNLTPS xmm1, xmm2; CMPPS xmm1,xmm2, 5
CMPNLEPS xmm1, xmm2; CMPPS xmm1,xmm2, 6
CMPORDPS xmm1, xmm2; CMPPS xmm1,xmm2, 7

CMPSS

格式:CMPSS xmm1, xmm2/m32, imm8

功能:低位单精度数做比较

算法:算法同CMPPS相似,只不过只是针对DEST[31-0]进行操作。

同样也可以利用可读性更好的指令

指令 实现
CMPEQSS xmm1, xmm2 CMPSS xmm1,xmm2, 0
CMPLTSS xmm1, xmm2 CMPSS xmm1,xmm2, 1
CMPLESS xmm1, xmm2 CMPSS xmm1,xmm2, 2
CMPUNORDSS xmm1, xmm2 CMPSS xmm1,xmm2, 3
CMPNEQSS xmm1, xmm2 CMPSS xmm1,xmm2, 4
CMPNLTSS xmm1, xmm2 CMPSS xmm1,xmm2, 5
CMPNLESS xmm1, xmm2 CMPSS xmm1,xmm2, 6
CMPORDSS xmm1, xmm2 CMPSS xmm1,xmm2, 7

COMISS

格式:COMISS xmm1, xmm2/m32

功能:比较低位数并且设置标识位

算法:

OF = 0;
SF = 0;
AF = 0;
IF ((DEST[31-0] UNORD SRC/m32[31-0]) = TRUE) THEN
 ZF = 1;
 PF = 1;
 CF = 1;
ELSEIF ((DEST[31-0] GTRTHAN SRC/m32[31-0]) = TRUE)THEN
 ZF = 0;
 PF = 0;
 CF = 0;
ELSEIF ((DEST[31-0] LESSTHAN SRC/m32[31-0]) = TRUE THEN
 ZF = 0;
 PF = 0;
 CF = 1;
ELSE
 ZF = 1;
 PF = 0;
 CF = 0;
FI

CVTPI2PS

格式:CVTPI2PS xmm, mm/m64

功能:32位整数转变为浮点数

算法:

DEST[31-0] = (float) (SRC/m64[31-0]) ;
DEST[63-32] = (float) (SRC/m64[63-32]);
DEST[95-64] = DEST[95-64] ;
DEST[127-96] = DEST[127-96];
CVTPS2PI

格式:CVTPS2PI mm, xmm/m64

功能:低位的两个浮点数转变为整数

算法:

DEST[31-0] = (int) (SRC/m64[31-0]);
DEST[63-32]= (int) (SRC/m64[63-32]);

CVTSI2SS

格式:CVTSI2SS xmm, r/m32

功能:32位整数转变为浮点数,存入低位

算法:

DEST[31-0] = (float) (R/m32);
DEST[63-32] = DEST[63-32] ;
DEST[95-64] = DEST[95-64] ;
DEST[127-96] = DEST[127-96];

CVTSS2SI

格式:CVTSS2SI r32, xmm/m32

功能:低位的浮点数转变为32位整数

算法:

r32 = (int) (SRC/m32[31-0]);

CVTTPS2PI

格式:CVTTPS2PI mm, xmm/m64

功能:低位的两个浮点数转变为整数,并且舍位

算法:

DEST[31-0] = (int) (SRC/m64[31-0]) ;
DEST[63-32] = (int) (SRC/m64[63-32]);

CVTTSS2SI

格式:CVTTSS2SI r32, xmm/ m32

功能:将最低位浮点数转换为整数,并舍位。

算法:

r32 = (INT) (SRC/m32[31-0]);

DIVPS

格式:DIVPS xmm1, xmm2/m128

功能:单精度数除法运算

算法:

DEST[31-0] = DEST[31-0] / (SRC/m128[31-0]) ;
DEST[63-32] = DEST[63-32] / (SRC/m128[63-32]) ;
DEST[95-64] = DEST[95-64] / (SRC/m128[95-64]) ;
DEST[127-96] = DEST[127-96] / (SRC/m128[127-96]);

DIVSS

格式:DIVSS xmm1, xmm2/m32

功能:低位单精度数除法

算法:

DEST[31-0] = DEST[31-0] / (SRC/m32[31-0]);
DEST[63-32] = DEST[63-32] ;
DEST[95-64] = DEST[95-64] ;
DEST[127-96] = DEST[127-96];

EMMS

格式:EMMS

功能:将浮点标识字置空

算法:

FPUTagWord <- FFFF

FXRSTOR

格式:FXRSTOR m512byte

功能:从m512byte中装入FP,MMX,以及SSE的状态

算法:

FP and MMX state and Streaming SIMD Extension state = m512byte;

FXSAVE

格式:FXSAVE m512byte

功能:向m512byte中存入FP,MMX,以及SSE的状态

算法:

m512byte = FP and MMX state and Streaming SIMD Extension state;

LDMXCSR

格式:LDMXCSR m32

功能:装入SSE的状态控制字

算法:

MXCSR = m32;

MAXPS

格式:MAXPS xmm1, xmm2/m128

功能:返回最大值

算法:

IF (DEST[31-0]=NaN) THEN
 DEST[31-0] = SRC[31-0];
ELSEIF (SRC[31-0] = NaN) THEN
 DEST[31-0] = SRC[31-0];
ELSEIF (DEST[31-0] > SRC/m128[31-0]) THEN
 DEST[31-0] = DEST[31-0];
ELSE
 DEST[31-0] = SRC/m128[31-0];
FI
IF (DEST[63-32]=NaN) THEN
 DEST[63-32] = SRC[63-32];
ELSEIF (SRC[63-32] = NaN) THEN
 DEST[63-32] = SRC[63-32];
ELSEIF (DEST[63-32] > SRC/m128[63-32]) THEN
 DEST[63-32] = DEST[63-32];
ELSE
 DEST[63-32] = SRC/m128[63-32];
FI
IF (DEST[95-64]=NaN) THEN
 DEST[95-64] = SRC[95-64];
ELSEIF (SRC[95-64] = NaN) THEN
 DEST[95-64] = SRC[95-64];
ELSEIF (DEST[95-64] > SRC/m128[95-64]) THEN
 DEST[95-64] = DEST[95-64];
ELSE
 DEST[95-64] = SRC/m128[95-64];
FI
IF (DEST[127-96]=NaN) THEN
 DEST[127-96] = SRC[127-96];
ELSEIF (SRC[127-96] = NaN) THEN
 DEST[127-96] = SRC[127-96];
ELSEIF (DEST[127-96] > SRC/m128[127-96]) THEN
 DEST[127-96] = DEST[127-96];
ELSE
 DEST[127-96] = SRC/m128[127-96];
FI

MAXSS

格式:MAXSS xmm1, xmm2/m32

功能:返回低位最大值

算法:同上面类似,区别在于只对DEST[31-0]进行操作

MINPS

格式:MINPS xmm1, xmm2/m128

功能:返回最小值

算法:略

MINSS

格式:MINSS xmm1, xmm2/m32

功能:返回低位最小值

算法:略

MOVAPS

格式:MOVAPS xmm1, xmm2/m128 或 MOVAPS xmm2/m128, xmm1

功能:对齐的数据传输指令

算法:

IF (destination = DEST) THEN
 IF (SRC = m128)THEN (* load instruction *)
 DEST[127-0] = m128;
 ELSE(* move instruction *)
 DEST[127=0] = SRC[127-0];
 FI;
ELSE
 IF (destination = m128)THEN (* store instruction *)
 m128 = SRC[127-0];
 ELSE(* move instruction *)
 DEST[127-0] = SRC[127-0];
 FI;
FI;
 
MOVHLPS

格式:MOVHLPS xmm1, xmm2

功能:高位的两个数传向低位

算法:

DEST[127-64] = DEST[127-64];
DEST[63-0] = SRC[127-64] ;

MOVHPS

格式:MOVHPS xmm, m64 或 MOVHPS m64, xmm

功能:高位数据传输指令

算法:

IF (destination = DEST) THEN(* load instruction *)
 DEST[127-64] = m64;
 DEST[31-0] = DEST[31-0];
 DEST[63-32] = DEST[63-32];
 ELSE (* store instruction *)
 m64 = SRC[127-64];
FI;
 
MOVLPS

格式:MOVLPS xmm, m64 或 MOVLPS m64, xmm

功能:低位数据传输指令

算法:

IF (destination = DEST) THEN(* load instruction *)
 DEST[63-0] = m64;
 DEST[95-64] = DEST[95-64];
 DEST[127-96] = DEST[127-96];
ELSE(* store instruction *)
 m64 = DEST[63-0];
FI
 
MOVLHPS

格式:MOVLHPS xmm1, xmm2

功能:低位的两个数传向高位

算法:

DEST[127-64] = SRC[63-0];
DEST[63-0] = DEST[63-0];

MOVMSKPS

格式:MOVMSKPS r32, xmm

功能:掩码移入32位寄存器

算法:

r32[0] = SRC[31] ;
r32[1] = SRC[63] ;
r32[2] = SRC[95] ;
r32[3] = SRC[127];
r32[7-4] = 0X0 ;
r32[15-8] = 0X00 ;
r32[31-16] = 0X0000 ;

MOVNTPS

格式:MOVNTPS m128, xmm

功能:将数据直接存入内存,减小对缓存的压力

算法:

m128 = SRC;

MOVSS

格式:MOVSS xmm1, xmm2/m32 或 MOVSS xmm2/m32, xmm1

功能:最低位数据的传输指令

算法:

IF (destination = DEST) THEN
 IF (SRC == m32) THEN(* load instruction *)
 DEST[31-0] = m32;
 DEST [63-32] = 0X00000000;
 DEST [95-64] = 0X00000000;
 DEST [127-96] = 0X00000000;
 ELSE(* move instruction *)
 DEST [31-0] = SRC[31-0];
 DEST [63-32] = DEST [63-32];
 DEST [95-64] = DEST [95-64];
 DEST [127-96] = DEST [127-96];
 FI
ELSE
 IF (destination = m32) THEN(* store instruction *)
 m32 = SRC[31-0];
 ELSE (* move instruction *)
 DEST [31-0] = SRC[31-0]
 DEST [63-32] = DEST[63-32];
 DEST [95-64] = DEST [95-64];
 DEST [127-96] = DEST [127-96];
 FI
FI

MOVUPS

格式:MOVUPS xmm1, xmm2/m128 或 MOVUPS xmm2/m128, xmm1

功能:非对齐数据的传输指令

算法:

IF (destination = xmm) THEN
 IF (SRC = m128)THEN(* load instruction *)
 DEST[127-0] = m128;
 ELSE (* move instruction *)
 DEST[127-0] = SRC[127-0];
 FI
ELSE
 IF (destination = m128) THEN(* store instruction *)
 m128 = SRC[127-0];
 ELSE (* move instruction *)
 DEST[127-0] = SRC[127-0];
 FI
FI

MULPS

格式:MULPS xmm1, xmm2/m128

功能:单精度数相乘

算法:

DEST[31-0] = DEST[31-0] * SRC/m128[31-0] ;
DEST[63-32] = DEST[63-32] * SRC/m128[63-32] ;
DEST[95-64] = DEST[95-64] * SRC/m128[95-64] ;
DEST[127-96] = DEST[127-96] * SRC/m128[127-96];

MULSS

格式:MULSS xmm1, xmm2/m32

功能:最低位的单精度数相乘

算法:

DEST[31-0] = DEST[31-0] * SRC/m32[31-0];
DEST[63-32] = DEST[63-32] ;
DEST[95-64] = DEST[95-64] ;
DEST[127-96] = DEST[127-96];

ORPS

格式:ORPS xmm1, xmm2/m128

功能:求或运算

算法:

DEST[127-0] |= SRC/m128[127-0];
RCPPS

格式:RCPPS xmm1, xmm2/m128

功能:求倒数的近似值

算法:

DEST[31-0] = APPROX (1.0/(SRC/m128[31-0])) ;
DEST[63-32] = APPROX (1.0/(SRC/m128[63-32])) ;
DEST[95-64] = APPROX (1.0/(SRC/m128[95-64])) ;
DEST[127-96] = APPROX (1.0/(SRC/m128[127-96]));

RCPSS

格式:RCPSS xmm1, xmm2/m32

功能:求最低位的倒数的近似值

算法:

DEST[31-0] = APPROX (1.0/(SRC/m32[31-0]));
DEST[63-32] = DEST[63-32] ;
DEST[95-64] = DEST[95-64] ;
DEST[127-96] = DEST[127-96];

RSQRTPS

格式:RSQRTPS xmm1, xmm2/m128

功能:求倒数平方根的近似值

算法:

DEST[31-0] = APPROX (1.0/SQRT(SRC/m128[31-0])) ;
DEST[63-32] = APPROX (1.0/SQRT(SRC/m128[63-32])) ;
DEST[95-64] = APPROX (1.0/SQRT(SRC/m128[95-64])) ;
DEST[127-96] = APPROX (1.0/SQRT(SRC/m128[127-96]));

RSQRTSS

格式:RSQRTSS xmm1, xmm2/m32

功能:求最低位倒数平方根的近似值

算法:

DEST[31-0] = APPROX (1.0/SQRT(SRC/m32[31-0]));
DEST[63-32] = DEST[63-32] ;
DEST[95-64] = DEST[95-64] ;
DEST[127-96] = DEST[127-96];

SHUFPS

格式:SHUFPS xmm1, xmm2/m128, imm8

功能:打乱顺序

算法:

FP_SELECT = (imm8 >> 0) AND 0X3;
IF (FP_SELECT = 0) THEN
 DEST[31-0] = DEST[31-0];
ELSEIF (FP_SELECT = 1) THEN
 DEST[31-0] = DEST[63-32];
ELSEIF (FP_SELECT = 2) THEN
 DEST[31-0] = DEST[95-64];
ELSE
 DEST[31-0] = DEST[127-96];
FI

FP_SELECT = (imm8 >> 2) AND 0X3;
IF (FP_SELECT = 0) THEN
 DEST[63-32] = DEST[31-0];
ELSEIF (FP_SELECT = 1) THEN
 DEST[63-32] = DEST[63-32];
ELSEIF (FP_SELECT = 2) THEN
 DEST[63-32] = DEST[95-64];
ELSE
 DEST[63-32] = DEST[127-96];
FI

FP_SELECT = (imm8 >> 4) AND 0X3;
IF (FP_SELECT = 0) THEN
 DEST[95-64] = SRC/m128[31-0];
ELSEIF (FP_SELECT = 1) THEN
 DEST[95-64] = SRC/m128 [63-32];
ELSEIF (FP_SELECT = 2) THEN
 DEST[95-64] = SRC/m128 [95-64];
ELSE
 DEST[95-64] = SRC/m128 [127-96];
FI

FP_SELECT = (imm8 >> 6) AND 0X3;
IF (FP_SELECT = 0) THEN
 DEST[127-96] = SRC/m128 [31-0];
ELSEIF (FP_SELECT = 1) THEN
 DEST[127-96] = SRC/m128 [63-32];
ELSEIF (FP_SELECT = 2) THEN
 DEST[127-96] = SRC/m128 [95-64];
ELSE
 DEST[127-96] = SRC/m128 [127-96];
FI

SQRTPS

格式:SQRTPS xmm1, xmm2/m128

功能:求平方根

算法:

DEST[31-0] = SQRT (SRC/m128[31-0] );
DEST[63-32] = SQRT (SRC/m128[63-32]);
DEST[95-64] = SQRT (SRC/m128[95-64]);
DEST[127-96] = SQRT (SRC/m128[127-96]);

SQRTSS

格式:SQRTSS xmm1, xmm2/m32

功能:最低位数求平方根

算法:

DEST[31-0] = SQRT (SRC/m32[31-0]);
DEST[63-32] = DEST[63-32];
DEST[95-64] = DEST[95-64];
DEST[127-96] = DEST[127-96];

STMXCSR

格式:STMXCSR m32

功能:存储SSE控制字

算法:

m32 = MXCSR;

SUBPS

格式:SUBPS xmm1, xmm2/m128

功能:单精度数的减法运算

算法:

DEST[31-0] = DEST[31-0] - SRC/m128[31-0] ;
DEST[63-32] = DEST[63-32] - SRC/m128[63-32];
DEST[95-64] = DEST[95-64] - SRC/m128[95-64];
DEST[127-96] = DEST[127-96] - SRC/m128[127-96];

SUBSS

格式:SUBSS xmm1, xmm2/m32

功能:最低位数相减

算法:

DEST[31-0] = DEST[31-0] - SRC/m32[31-0];
DEST[63-32] = DEST[63-32];
DEST[95-64] = DEST[95-64];
DEST[127-96] = DEST[127-96];

UCOMISS

格式:UCOMISS xmm1, xmm2/m32

功能:比较低位数并且设置标志位

算法:

OF = 0;
SF = 0;
AF = 0;
IF ((DEST[31-0] UNORD SRC/m32[31-0]) = TRUE) THEN
 ZF = 1;
 PF = 1;
 CF = 1;
ELSEIF ((DEST[31-0] GTRTHAN SRC/m32[31-0]) = TRUE)THEN
 ZF = 0;
 PF = 0;
 CF = 0;
ELSEIF ((DEST[31-0] LESSTHAN SRC/m32[31-0]) = TRUE THEN
 ZF = 0;
 PF = 0;
 CF = 1;
ELSE
 ZF = 1;
 PF = 0;
 CF = 0;
FI

UNPCKHPS

格式:UNPCKHPS xmm1, xmm2/m128

功能:高位两数交替传输

算法:

DEST[31-0] = DEST[95-64];
DEST[63-32] = SRC/m128[95-64];
DEST[95-64] = DEST[127-96];
DEST[127-96] = SRC/m128[127-96];

UNPCKLPS

格式:UNPCKLPS xmm1, xmm2/m128

功能:低位两数交替传输

算法:

DEST[31-0] = DEST[31-0];
DEST[63-32] = SRC/m128[31-0];
DEST[95-64] = DEST[63-32];
DEST[127-96] = SRC/m128[63-32];

XORPS

格式:XORPS xmm1, xmm2/m128

功能:异或运算

算法:

DEST[127-0] = DEST/m128[127-0] XOR SRC/m128[127-0]

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

MMX及SSE优化--SSE篇 的相关文章

随机推荐

  • 多线程竞争及解决方法

    线程是非独立的 同一个进程里线程的数据是共享的 当各个线程访问数据资源时会出现竞争状态 即 数据几乎同步会被多个线程占用 造成数据混乱 即所谓的线程不安全 解决多线程问题的方法 锁 锁的好处 确保了某段关键代码 共享数据资源 只能有一个线程
  • 树莓派3B+安装Raspbian简易教程

    刚买的树莓派3B 没过一周 树莓派4就出来了 不过算了 基本上用起来差不多 所以大家继续看吧 最近有点忙 所以就不BB了 直接上主题 下载Raspbian Raspbian是树莓派的官方系统 推荐大家使用 如果不喜欢它的话 可以自己安装Ub
  • DynamicDataSource是如何解决多数据源的事务问题?

    多数据源的真面目DynamicRoutingDataSource DynamicRoutingDataSource是什么 该类实现了DataSource接口并在内部维护了一个map 其中存放了多个真实的DataSource 而key则是不同
  • 启动 GDB 调试

    使用 GDB 调试程序一般有三种方式 gdb filename gdb attach pid gdb filename corename 这也对应着本节课的核心内容 直接调试目标程序 附加进程 调试 core 文件 接下来我们逐一讲解 直接
  • Vim重复命令

    1 vim重复命令 重复执行上次命令 普通模式下输入 x 删除第一个字符 然后输入 会再次删除一个字符 重复了 x 的操作 执行指定次数相同的命令 普通模式下输入 N N表示重复后面的次数 例如 输入10x 删除10个连续字符 输入3dd
  • Jquery水平滚动字幕(marquee效果)

    水平滚动字幕 html div class txt scroll div class scrollbox div class txt div div div css txt scroll width 100 line height 1rem
  • VS或者Qt调用外部动态链接库dll的方法

    1 VS调用外部动态链接库dll的方法 Windows 1 1 建立一个Win32控制台应用程序 1 2 如果搭建的是64位应用 需将平台调整为x64 1 3 将程序源码和头文件 动态链接库和静态连接库拷贝到项目对应的文件夹中 1 4 将上
  • Spring依赖注入和控制反转

    文章目录 1 依赖注入 1 1 依赖注入和控制反转的概念 1 2 依赖注入的实现方式 1 3 控制反转的具体实现 1 4 依赖注入的具体实现 1 5 依赖注入和控制反转总结 1 依赖注入 1 1 依赖注入和控制反转的概念 依赖注入 Depe
  • 前后端分离(axios发送数据请求,路由导航守卫,web会话跟踪,token)

    目录 1 前端登录发起请求 a 在 main js 中配置 axios b 组装请求数据 3 连接数据库 4 后端响应 5 前端处理 6 来到main组件时 需在前端判断用户是否登录 7 web会话跟踪技术 token 8 响应拦截器 9
  • os.path.expanduser

    path os path expanduser linux系统path为 home newt windows系统path为 C Users newt 其中newt为我的用户名
  • XSS攻击修改服务器的代码,XSS攻击的定义,类型以及防御方法

    经常跟大家讲 CC攻击 好像还没有给大家分享过XSS攻击它的类型怎么去防御 今天云都小编就带大家了解下 什么是XSS攻击 XXS 攻击全称跨站脚本攻击 是一种在Web应用中的计算机安全漏洞 它允许恶意Web用户将代码植入到提供给其他使用的页
  • 《机器学习》实验五:实现K-means聚类

    机器学习 实验五 实现K means聚类 机器学习 实验五 实现K means聚类 实验目的 实验原理 实验内容与要求 实验器材 设备 元器件 实验步骤 心得体会 机器学习 实验五 实现K means聚类 实验目的 了解聚类的基本概念 掌握
  • javascript对象小探之三——undefined和undeclared

    一 undefined undefined是javascript的一个数据类型对象 var i 那么i的值就是undefined 二 undeclared undeclared是一种语法错误 不是数据类型 不要误会了 但是js引擎不会报错
  • R语言学习笔记(三)数据处理

    本文的示例数据框集 egData 如下 值标签 if FALSE 值标签 levels代表变量实际值 labels代表标签值 egData sex lt factor egData sex levels c 1 2 labels c mal
  • WSL2+Docker+IDEA一站式开发调试

    WSL2 Docker IDEA一站式开发调试 将就看吧 不知道为什么CSDN无法转储并展示jsdelivr的图片 但博客园正常展示 前言 我们知道 Docker是一个容器引擎 对于开发者来说 使用Dokcer容器部署各种开发需要的中间件
  • linux端口开放指定端口的两种方法

    开放端口的方法 方法一 命令行方式 1 开放端口命令 sbin iptables I INPUT p tcp dport 8080 j ACCEPT 2 保存 etc rc d init d iptables save 3 重启服务 etc
  • 正则表达式和三剑客

    正则表达式与三剑客 Linux正则表达式 由一类特殊字符及文本字符所编写的模式 其中有些字符不表示其字面意义 而是用于表示控制或通配符的功能 分两类 基本正则表达式 BRE 扩展正则表达式 ERE 基本正则表达式DRE集合 元字符 作用 只
  • ROS环境搭建步骤总结

    ROS环境搭建踩坑总结 Ubuntu 16 04安装ROS Kinetic ROS安装 进入到 ROS官网选择安装的版本和系统 配置Ubuntu的repositories 以允许 restricted universe 和 multiver
  • vue element el-select下拉选择不回显问题

    el select下拉选择无效 问题描述 在使用Vue开发使用element ui时 el select下拉框出现在点击选择的时候数据无法显示的问题
  • MMX及SSE优化--SSE篇

    上回讲到针对整数运算的MMX优化技术 然而真正大运算量的图形和声音处理大都用的是浮点运算 而且现在对浮点运算的要求也是越来越高 在这样一个条件下INTEL终于在Pentium III处理中增加针对浮点运算优化的SSE指令 所以所有用过SSE