有用过SSE的么?怎么发现SSE居然比C还慢,帖子内有代码大家可以自己编译运行试试看!!!

梁跃 2006-04-11 09:47:37
下面的代码是计算向量归一化到单位向量,可以直接编译运行,发现C的版本要远快于SSE的版本,不知道是程序写的有问题还是SSE的确不行!

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include <conio.h>
typedef _declspec(align(16)) float vec3_t[3];


inline void vec_normalize_sse(vec3_t vec)
{
_asm {
mov esi, vec
movaps xmm0, [esi]
movaps xmm1, xmm0
mulps xmm1, xmm1

movaps xmm2, xmm1
shufps xmm2, xmm1, 0xe1
movaps xmm3, xmm1
shufps xmm3, xmm1, 0xc6
addps xmm1, xmm2
addps xmm1, xmm3

shufps xmm1, xmm1, 0x00
sqrtps xmm1, xmm1
divps xmm0, xmm1

movaps [esi], xmm0
}
}


inline void vec_normalize_c(vec3_t vec)
{
float len;
len = vec[0]*vec[0] + vec[1]*vec[1] + vec[2]*vec[2];
len = (float)sqrt(len);
len = 1.0f/len;
vec[0] *= len;
vec[1] *= len;
vec[2] *= len;
}

int main()
{
int i, s, e, count;
vec3_t vec;

count = 10000000;

vec[0] = 1.0f;
vec[1] = 2.0f;
vec[2] = 3.0f;
s = clock();
for (i = 0; i < count; i++) {
vec_normalize_sse(vec);
}
e = clock();
printf("sse = %d, %f, %f, %f\n", e - s, vec[0], vec[1], vec[2]);

vec[0] = 1.0f;
vec[1] = 2.0f;
vec[2] = 3.0f;
s = clock();
for (i = 0; i < count; i++) {
vec_normalize_c(vec);
}
e = clock();
printf("c = %d, %f, %f, %f\n", e - s, vec[0], vec[1], vec[2]);
getch();
return 0;
}
...全文
516 18 打赏 收藏 转发到动态 举报
写回复
用AI写文章
18 条回复
切换为时间正序
请发表友善的回复…
发表回复
梁跃 2006-04-16
  • 打赏
  • 举报
回复
to redleaves(ID最吊的网友)
能具体讲一下你使用SSE在游戏中优化的具体考虑和环节么?
redleaves 2006-04-15
  • 打赏
  • 举报
回复
楼主,我说的大块数据并不是指那种连续的数据块,而是指大量的数据,可以是以离散的.如果测试仅局限于只针对一组数据,那的确,在PM芯片上一般的浮点指令是要比SSE快一点,但对于很多组数据来说,SSE就有优势了,因为它SIMD特性,它的数据吞吐能力大大超过FPU的指令.
通常的简单数值运算,SSE并不能带来性能上的优势.优化程序要充分利用指令的特性,比如SSE有饱和加指令,那你在做饱和加的运算时,它就比一般指令要快得多.但SSE操作要把数据打包,对数据的组织也有要求,这就带来的另外的开销.这之间的取舍关系,只有你自己把握了.
再就是用SSE不光是用来优化这些基础运算的,最主要的是用来优化并行运算,因为它一次可以处理一组数据,在设计算法的时候,你就要考虑到这个特性,也许做单值的运算,它并不快,但它一次可以干其它指令四倍或更多的工作,这时,你的算法就不能再像以前一样,每次只处理一组数据,这样完全不能发挥出SSE的优势.
还有在很多情况下,这种指令优化所带来的好处不及你算法稍稍优化一点的好处.而且用C函数,编译器在做内联的时候会进一步优化,就算SSE的函数要快一点,但一内联就差不多了.有的运算则完全不适合用SSE来做.
redleaves 2006-04-14
  • 打赏
  • 举报
回复
TO Leo1981816(狮子座):
不管是不是inline SSE的都应该比C的快啊,我之后以用noinline是为了让比较结果更接近真实结果,因为inline在不同的地方可能有不同的优化结果.
你用的是什么编译器,CPU是什么?你把你的测试结果给出来看看呢?

我的机器是P4 3.0E, 1G DDR400 RAM, 用VC 7.1/VC 8.1/ICL 9.0 都是这样的.
梁跃 2006-04-14
  • 打赏
  • 举报
回复
请问在一个3D管线中比较适合用SSE进行优化的地方是哪里?我试图在光栅化阶段进行优化,但基本上没有起到优化的作用,同时我也在基本的3D几何运算函数进行了SSE优化,很多3D功能都建立在这些函数的基础之上,由于这些优化后的基础函数性能反而下降导致整体性能的下降。
如果按照上面的大块数据方式组织定点,面等信息也不现实,在经过背面消除,视见体剪切之后这些数据并不连续(有的定点或者面已经被删除了),那么上面的所谓大块数据是否还有意义?
同时照理说,如果单个函数的性能都得不到优化,那么怎么谈得上对大块数据多次调用仍然有优化可言?
schwarzenegger 2006-04-14
  • 打赏
  • 举报
回复
因为是CISC指令,,SSE指令周期长,在简单的功能上,C比SSE快是可能的。
如果进行大量复杂的运算SSE应该会快的。
redleaves 2006-04-14
  • 打赏
  • 举报
回复
另外,这种测试太过片面,你应该用实际数据来测试,至少用大块的数据块来测试,也比用这种单一值的测试, 如下:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include <conio.h>
typedef _declspec(align(16)) float vec3_t[4];

__forceinline void vec_normalize_sse(vec3_t vec)
{
_asm {
mov esi, vec
movaps xmm0, [esi]
movaps xmm1, xmm0
mulps xmm1, xmm1

movaps xmm2, xmm1
shufps xmm2, xmm1, 0xe1
movaps xmm3, xmm1
shufps xmm3, xmm1, 0xc6
addps xmm1, xmm2
addps xmm1, xmm3

shufps xmm1, xmm1, 0x00
sqrtps xmm1, xmm1
divps xmm0, xmm1

movaps [esi], xmm0
}
}

__forceinline void vec_normalize_sse2(vec3_t vec)
{
_asm {
mov esi, vec
movaps xmm1, [esi]
movaps xmm0, xmm1
mulps xmm1, xmm1

movaps xmm2, xmm1
shufps xmm2, xmm1, 0x09
movaps xmm3, xmm2
shufps xmm3, xmm2, 0x09
addps xmm1, xmm2
addps xmm1, xmm3

sqrtps xmm1, xmm1
divps xmm0, xmm1

movaps [esi], xmm0
}
}

__forceinline void vec_normalize_sse3(vec3_t vec)
{
_asm {
mov esi, vec
movaps xmm1, [esi]
movaps xmm0, xmm1
mulps xmm1, xmm1

movaps xmm2, xmm1
shufps xmm2, xmm1, 0x09
movaps xmm3, xmm2
shufps xmm3, xmm2, 0x09
addps xmm1, xmm2
addps xmm1, xmm3

sqrtps xmm1, xmm1
rcpps xmm1, xmm1
mulps xmm0, xmm1

movaps [esi], xmm0
}
}


__forceinline void vec_normalize_c(vec3_t vec)
{
float len;
len = vec[0]*vec[0] + vec[1]*vec[1] + vec[2]*vec[2];
len = (float)sqrt(len);
len = 1.0f/len;
vec[0] *= len;
vec[1] *= len;
vec[2] *= len;
}


int main(void)
{
int i, s, e, count;
vec3_t * vec = new vec3_t[0xFFFFFF];

count = 0xFFFFFF;

for( int t = 0; t<3; t++ ) {

for (i = 0; i < count; i++) {
vec[i][0] = 1.0f;
vec[i][1] = 2.0f;
vec[i][2] = 3.0f;
}
s = clock();
for (i = 0; i < count; i++) {
vec_normalize_sse(vec[i]);
}
e = clock();
printf("sse = %d, %f, %f, %f\n", e - s, vec[0][0], vec[0][1], vec[0][2]);

for (i = 0; i < count; i++) {
vec[i][0] = 1.0f;
vec[i][1] = 2.0f;
vec[i][2] = 3.0f;
}
s = clock();
for (i = 0; i < count; i++) {
vec_normalize_sse2(vec[i]);
}
e = clock();
printf("sse2 = %d, %f, %f, %f\n", e - s, vec[0][0], vec[0][1], vec[0][2]);

for (i = 0; i < count; i++) {
vec[i][0] = 1.0f;
vec[i][1] = 2.0f;
vec[i][2] = 3.0f;
}
s = clock();
for (i = 0; i < count; i++) {
vec_normalize_sse3(vec[i]);
}
e = clock();
printf("sse3 = %d, %f, %f, %f\n", e - s, vec[0][0], vec[0][1], vec[0][2]);

for (i = 0; i < count; i++) {
vec[i][0] = 1.0f;
vec[i][1] = 2.0f;
vec[i][2] = 3.0f;
}
s = clock();
for (i = 0; i < count; i++) {
vec_normalize_c(vec[i]);
}
e = clock();
printf("c = %d, %f, %f, %f\n", e - s, vec[0][0], vec[0][1], vec[0][2]);
}
delete[] vec;
return 0;
}

测试结果如下:

P4 3.0E
sse = 515, 0.267261, 0.534522, 0.801784
sse2 = 500, 0.267261, 0.534522, 0.801784
sse3 = 359, 0.267273, 0.534546, 0.801819
c = 1375, 0.267261, 0.534522, 0.801784
sse = 515, 0.267261, 0.534522, 0.801784
sse2 = 515, 0.267261, 0.534522, 0.801784
sse3 = 360, 0.267273, 0.534546, 0.801819
c = 1359, 0.267261, 0.534522, 0.801784
sse = 516, 0.267261, 0.534522, 0.801784
sse2 = 516, 0.267261, 0.534522, 0.801784
sse3 = 359, 0.267273, 0.534546, 0.801819
c = 1360, 0.267261, 0.534522, 0.801784

PM 1.73
sse = 932, 0.267261, 0.534522, 0.801784
sse2 = 911, 0.267261, 0.534522, 0.801784
sse3 = 581, 0.267273, 0.534546, 0.801819
c = 1503, 0.267261, 0.534522, 0.801784
sse = 901, 0.267261, 0.534522, 0.801784
sse2 = 901, 0.267261, 0.534522, 0.801784
sse3 = 571, 0.267273, 0.534546, 0.801819
c = 1502, 0.267261, 0.534522, 0.801784
sse = 921, 0.267261, 0.534522, 0.801784
sse2 = 901, 0.267261, 0.534522, 0.801784
sse3 = 571, 0.267273, 0.534546, 0.801819
c = 1502, 0.267261, 0.534522, 0.801784

如果用这种大块数据来测试,结果就相差十万八千里了.
redleaves 2006-04-14
  • 打赏
  • 举报
回复
如果是用__forceinline
P4 3.0E
sse = 4484, 0.267261, 0.534523, 0.801784
sse2 = 484, 0.267261, 0.534523, 0.801784
sse3 = 407, 0.267273, 0.534546, 0.801880
c = 437, 0.267261, 0.534522, 0.801784
sse = 516, 0.267261, 0.534523, 0.801784
sse2 = 484, 0.267261, 0.534523, 0.801784
sse3 = 391, 0.267273, 0.534546, 0.801880
c = 437, 0.267261, 0.534522, 0.801784
sse = 500, 0.267261, 0.534523, 0.801784
sse2 = 485, 0.267261, 0.534523, 0.801784
sse3 = 390, 0.267273, 0.534546, 0.801880
c = 438, 0.267261, 0.534522, 0.801784

PM 1.73
sse = 1231, 0.267261, 0.534523, 0.801784
sse2 = 541, 0.267261, 0.534523, 0.801784
sse3 = 501, 0.267273, 0.534546, 0.801880
c = 230, 0.267261, 0.534522, 0.801784
sse = 561, 0.267261, 0.534523, 0.801784
sse2 = 551, 0.267261, 0.534523, 0.801784
sse3 = 500, 0.267273, 0.534546, 0.801880
c = 231, 0.267261, 0.534522, 0.801784
sse = 571, 0.267261, 0.534523, 0.801784
sse2 = 540, 0.267261, 0.534523, 0.801784
sse3 = 491, 0.267273, 0.534546, 0.801880
c = 230, 0.267261, 0.534522, 0.801784

和你说的情况是一样的,这样的话就没有办法了.说明在PM芯片上,在循环中执行FPU指令比SSE要快得多,不过在其它的机器上还是SSE要快.
你也可以看到,如果不用内联,这些代码
redleaves 2006-04-14
  • 打赏
  • 举报
回复
这下我不明白你的机器或是编译器是怎么回事了. 我刚才找了两台机器测试一下,结果如下
P4 2.4B 超2.8 1G RAM
sse = 6796, 0.267261, 0.534523, 0.801784
sse2 = 485, 0.267261, 0.534523, 0.801784
sse3 = 422, 0.267273, 0.534546, 0.801880
c = 531, 0.267261, 0.534522, 0.801784
sse = 547, 0.267261, 0.534523, 0.801784
sse2 = 484, 0.267261, 0.534523, 0.801784
sse3 = 406, 0.267273, 0.534546, 0.801880
c = 547, 0.267261, 0.534522, 0.801784
sse = 532, 0.267261, 0.534523, 0.801784
sse2 = 500, 0.267261, 0.534523, 0.801784
sse3 = 406, 0.267273, 0.534546, 0.801880
c = 531, 0.267261, 0.534522, 0.801784

PM 1.73 1G RAM
sse = 1241, 0.267261, 0.534523, 0.801784
sse2 = 551, 0.267261, 0.534523, 0.801784
sse3 = 491, 0.267273, 0.534546, 0.801880
c = 681, 0.267261, 0.534522, 0.801784
sse = 561, 0.267261, 0.534523, 0.801784
sse2 = 550, 0.267261, 0.534523, 0.801784
sse3 = 491, 0.267273, 0.534546, 0.801880
c = 691, 0.267261, 0.534522, 0.801784
sse = 551, 0.267261, 0.534523, 0.801784
sse2 = 551, 0.267261, 0.534523, 0.801784
sse3 = 490, 0.267273, 0.534546, 0.801880
c = 691, 0.267261, 0.534522, 0.801784

这两组结果和我第一次给出的结果是一致的.
我用的是7.1 编译的命令是 cl test.cpp /O2
Leomaxking 2006-04-14
  • 打赏
  • 举报
回复
O
redleaves 2006-04-14
  • 打赏
  • 举报
回复
你的机器的情况我没有试过,等晚上回去在我的笔记本上试一下就知道了.
我以前帮别人做过游戏优化,用SSE和3DNOW,至少在P4的机器上,SSE代码比绝大多数的C代码要快得多.PM和内核和P4不一样,就不好说了.建议你用Intel的编译器编译一下,打开SSE优化,看看Intel生成的SSE代码是怎么样的.
梁跃 2006-04-14
  • 打赏
  • 举报
回复
我的机器是IBM R50, PM1.6, 512M, VS2003
测试结果
C:300ms
SSE:611ms

我在写一个3D图形库,如果说对向量进行单位化的代码比较简单可能会出现C比SSE快的现象,那么我也用SSE改写了光栅化阶段的代码,同样是C更快些,至少会不比SSE慢。
可以说到现在为止,我尝试的对SSE进行优化都没有取得理想的效果,最好的情况就是SSE优化后的程序与C的运算效率相当,不好的时候要明显比C慢。
国内关于这方面的资料很少
Vc_Atl 2006-04-13
  • 打赏
  • 举报
回复
gz
Source_Code 2006-04-13
  • 打赏
  • 举报
回复
个人认为C比SSE快是不可能的。.硬件实现比软件实现是快的。.
梁跃 2006-04-12
  • 打赏
  • 举报
回复
我测试的是你的代码,你的代码中SSE,SSE2,SSE3的效率都是稳定,而C版本慢的原因在于你使用的是__declspec(noinline) 方式,如果把__declspec(noinline)改成inline(SSE,..., C等版本都这样改)你在测测看

从测试结果来看不论是你的版本还是我的版本SSE运算效率基本上是一样,没有太大变化,你的C版本由于使用__declspec(noinline)导致效率下降。我的测试结果表明C版本几乎要比SSE快1倍
redleaves 2006-04-12
  • 打赏
  • 举报
回复
你用我给你贴的程序也是这个样子么?
你可以看到我贴的结果,第一次执行vec_normalize_sse是8400MS 之后就变成了500MS左右...
我以前测试C程序时也发现过这种问题,函数调用的位置不同,测试出来的结果相差很大.
你也可以换几个不同的编译器,这样测试出来的结果也会不一样.
这很可能是由于程序结结构不同,造成数据的内存布局不同,这样,有的时候就可能导致CPU的缓冲机制不能达到最优.比如你把数据对齐到32字节边界上,或是把数据放到堆里,就有可能得到不同的结果.
梁跃 2006-04-11
  • 打赏
  • 举报
回复
没人能够解答么?
梁跃 2006-04-11
  • 打赏
  • 举报
回复
我测试了一下代码,我的版本的SSE,和你改进后的SSE运算时间基本一致,但是C函数我的这个版本要快很多
redleaves 2006-04-11
  • 打赏
  • 举报
回复
楼上的,你的代码没借,而且SSE的的确经C的快,只是你的测试方式不太对,因为这种测试如果放到一个简单的环境里,CPU的缓冲机制不能达到最优状态,所以你的测试结果很可能不正确而且会差很远.如果把这个代码放到一个比较复杂的环境里,得出的结果可能会正确一些.

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include <conio.h>
typedef _declspec(align(16)) float vec3_t[3];

__declspec(noinline) void vec_normalize_sse(vec3_t vec)
{
_asm {
mov esi, vec
movaps xmm0, [esi]
movaps xmm1, xmm0
mulps xmm1, xmm1

movaps xmm2, xmm1
shufps xmm2, xmm1, 0xe1
movaps xmm3, xmm1
shufps xmm3, xmm1, 0xc6
addps xmm1, xmm2
addps xmm1, xmm3

shufps xmm1, xmm1, 0x00
sqrtps xmm1, xmm1
divps xmm0, xmm1

movaps [esi], xmm0
}
}

__declspec(noinline) void vec_normalize_sse2(vec3_t vec)
{
_asm {
mov esi, vec
movaps xmm1, [esi]
movaps xmm0, xmm1
mulps xmm1, xmm1

movaps xmm2, xmm1
shufps xmm2, xmm1, 0x09
movaps xmm3, xmm2
shufps xmm3, xmm2, 0x09
addps xmm1, xmm2
addps xmm1, xmm3

sqrtps xmm1, xmm1
divps xmm0, xmm1

movaps [esi], xmm0
}
}

__declspec(noinline) void vec_normalize_sse3(vec3_t vec)
{
_asm {
mov esi, vec
movaps xmm1, [esi]
movaps xmm0, xmm1
mulps xmm1, xmm1

movaps xmm2, xmm1
shufps xmm2, xmm1, 0x09
movaps xmm3, xmm2
shufps xmm3, xmm2, 0x09
addps xmm1, xmm2
addps xmm1, xmm3

sqrtps xmm1, xmm1
rcpps xmm1, xmm1
mulps xmm0, xmm1

movaps [esi], xmm0
}
}


__declspec(noinline) void vec_normalize_c(vec3_t vec)
{
float len;
len = vec[0]*vec[0] + vec[1]*vec[1] + vec[2]*vec[2];
len = (float)sqrt(len);
len = 1.0f/len;
vec[0] *= len;
vec[1] *= len;
vec[2] *= len;
}


int main(void)
{
int i, s, e, count;
vec3_t vec;

count = 10000000;

for( int t = 0; t<3; t++ ) {

vec[0] = 1.0f;
vec[1] = 2.0f;
vec[2] = 3.0f;
s = clock();
for (i = 0; i < count; i++) {
vec_normalize_sse(vec);
}
e = clock();
printf("sse = %d, %f, %f, %f\n", e - s, vec[0], vec[1], vec[2]);

vec[0] = 1.0f;
vec[1] = 2.0f;
vec[2] = 3.0f;
s = clock();
for (i = 0; i < count; i++) {
vec_normalize_sse2(vec);
}
e = clock();
printf("sse2 = %d, %f, %f, %f\n", e - s, vec[0], vec[1], vec[2]);

vec[0] = 1.0f;
vec[1] = 2.0f;
vec[2] = 3.0f;
s = clock();
for (i = 0; i < count; i++) {
vec_normalize_sse3(vec);
}
e = clock();
printf("sse3 = %d, %f, %f, %f\n", e - s, vec[0], vec[1], vec[2]);

vec[0] = 1.0f;
vec[1] = 2.0f;
vec[2] = 3.0f;
s = clock();
for (i = 0; i < count; i++) {
vec_normalize_c(vec);
}
e = clock();
printf("c = %d, %f, %f, %f\n", e - s, vec[0], vec[1], vec[2]);
}
return 0;
}

这里我帮你写了两个SSE的函数,vec_normalize_sse2比你的那个快一点点,精度一样.vec_normalize_sse3比你的那个快很多,但精度要低一点.当然,还可以写出介于vec_normalize_sse2和vec_normalize_sse3之间的,不过我想应该没必要了吧.
我的测试结果:
sse = 8437, 0.267261, 0.534523, 0.801784
sse2 = 469, 0.267261, 0.534523, 0.801784
sse3 = 375, 0.267273, 0.534546, 0.801880
c = 750, 0.267261, 0.534523, 0.801784
sse = 500, 0.267261, 0.534523, 0.801784
sse2 = 469, 0.267261, 0.534523, 0.801784
sse3 = 375, 0.267273, 0.534546, 0.801880
c = 718, 0.267261, 0.534523, 0.801784
sse = 485, 0.267261, 0.534523, 0.801784
sse2 = 468, 0.267261, 0.534523, 0.801784
sse3 = 391, 0.267273, 0.534546, 0.801880
c = 703, 0.267261, 0.534523, 0.801784
一套目前来说最好的nestjs实战教程,提供QQ长期问答服务. 本人从 08 年到 18 年一直从事于 PHP 的开发。从 18 年开始转向 Typescript+React+Nestjs 的技术栈。目前来说 React 应该是一个非常好用的前端框架,生态非常完善,并且十分灵活简单。Nestjs 则是 Node.js 中唯一且无敌存在的后端 web 框架。因为我个人从事这套技术栈开发已经 4 年多,所以颇有心得,做了这套 React18 视频教程和 Nestjs 实战视频教程。现在视频教程也是刚刚开始做了一部分,还在持续更新。使用 TS 全栈开发可以基本涵盖各种平台的方方面面,比如开发桌面应用的 Electron, 开发小程序的 Taro, 开发 Spa 中后台的 React,开发 SSR 网站的 next.js,开发移动应用的 React Native, 开发 CLI 的 Yargs, 以及开发后端的 Nestjs。基本学会一套,全面够用,再加上 Monorepo 组织结构,一个仓库所有平台都可以搞定。 包含以下知识点 - 掌握Nestjs框架的依赖注入,模块,提供者,生命周期等概念- 掌握DTO数据验证,响应序列化,异常过滤器等常用功能- 学会编写一些常用的class-validator验证约束- 熟练掌握Typeorm以及Nestjs与Typeorm结合开发- 学会整合Swagger输出Open API文档- 掌握TS装饰器以及反射元数据的定义和使用- 编写一些数据库相关的数据验证约束(比如树形表的同级别某字段唯一验证等)- 学会通过继承并魔改Nestjs源码编写自定义的全局验证器- 可以编写自定义的配置系统以及核心功能包- 学会自定义的代码组织方式(比如教程中我把默认的Nestjs应用改成Util+PluginModule模式)- 掌握编写一些常用的Util仓库(比如数据库,Redis,Restful)- 利用Yargs结合魔改后的框架可以编写一些自定义CLI命令(比如数据迁移,数据填充等)- 掌握如何利用阿里云/腾讯云推送邮件和短信- 掌握使用消息列队(MQ)的方式异步推送邮件和短信- 掌握守卫原理以及编写一些用户验证的守卫- 编写一个完善的用户系统(JWT认证,短信/邮件登录,短信/邮件注册,找回密码,绑定手机和邮箱等)- 熟练地通过编写装饰器去实现一些常用的功能- 通过SSE,WebSockets实现用户的上线,下线以及消息实时推送,消息广播等- 学会使用云存储来上传文件- 学会大文件断点雪川- 实现RBAC的权限系统- 理解请求范围概念以及性能方便的考量- 自己构建配置系统,实现配置验证以及通过YAML或数据库来进行动态配置- 通过适用Vscode进行Debug以及编写Jest测试来提升开发效率与程序的可用性- 学会使用Node来编写自定义的CLI命令- 利用NestCURD进行快速开发- 学会Graphql替代Restful写API- 使用Mongodb替代关系型数据库- 掌握一些常用的打包工具,比如通过ncc打包成单文件,通过pack打包成二进制等- 学会一些常用的部署方式,比如通过nginx+pm2反向代理部署,devops自动化CI,CD等- 学会使用pnpm workspaces来使用monreopo组织代码

21,459

社区成员

发帖
与我相关
我的任务
社区描述
汇编语言(Assembly Language)是任何一种用于电子计算机、微处理器、微控制器或其他可编程器件的低级语言,亦称为符号语言。
社区管理员
  • 汇编语言
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧