vscode里混合调试c++和nodejs

由于业务里涉及到 js 和 c++互相调用,为了调试方便,研究下如何在 vscode 里混合调试 c++和 js 代码。

c++开发和调试

在讲混合调试之前,先简单介绍下 vscode 下 c++的开发和调试,后续所有都是在 Mac OS 环境下操作的。

前置条件

安装 c++套件 c++ extension
安装 lldb 套件 vscode-lldb
确认安装 clang

混合调试

因为 c++和 nodejs 走的是不同的调试协议,因此很难通过一个 configuration 来调试两者。 我们以 node 官方的 example https://github.com/nodejs/node-addon-examples/tree/master/1_hello_world/nan, 看看如何进行混合调试

addon 编译

创建 addon 的编译 script

1
2
3
4
5
6
7
8
"scripts": {
"start": "node index.js",
"build:dev": "node-gyp -j 16 build --debug", // 编译带上debug信息
"build": "node-gyp -j 16 build",
"rebuild:dev": "node-gyp -j 16 rebuild --debug",
"rebuild": "node-gyp -j 16 rebuild",
"clean": "node-gyp clean"
},

创建 preLaunchTask

调试程序前,我们需要预先编译好可以 debug 的 addon,因此我们创建一个 preLaunchTask,选择 rebuild:dev,其负责编译一个可以 debug 的 addon 版本
img

创建 launch.json

我们新创建一个启动 node 的 launch,不过我们这里使用 lldb 来启动 node,配置如下

1
2
3
4
5
6
7
8
{
"type": "lldb",
"request": "launch",
"name": "lldb:node",
"program": "/Users/yj/.nvm/versions/node/v12.16.1/bin/node", // 指向node入科
"args": ["examples/addon/index.js"], // 指向js入口
"cwd": "${workspaceFolder}"
},

此时我们启动 lldb:node 就可以进入 node 的 addon 进行 debug

img

这里存在的问题在于,我们这里实际上是使用 lldb 来调试 node 程序(此时的 addon 实际上是一个动态库),lldb 实际上对 js 的调试是无感知的,因此我们这样实际是无法调试 js 的,在 js 里打下的断点也无法进入。

nodejs 调试

实际上 node 的 js 里的调试功能实际上是通过 chrome debugger protocol 协议来实现的,因此我们只需要启动 js 的时候,开启 inspector 协议就然后就可以 attach 到 js 上进行调试。 修改配置,开启 inspector 协议

1
2
3
4
5
6
7
8
{
"type": "lldb",
"request": "launch",
"name": "lldb:node",
"program": "/Users/yj/.nvm/versions/node/v12.16.1/bin/node",
"args": ["--inspect-brk","examples/addon/index.js"], // 开启inspector协议
"cwd": "${workspaceFolder}"
},

此时我们重新启动 lldb:node,发现在终端出来个 websocket 地址
img

在 vscode 里调试 js

实际上当 node 开启 inspector 协议的时候,不仅可以通过 ws attach 到 node 的 js 上,实际上也可以通过 http:port attach 到 js 上。实际上我们的 ws 地址也是从这个 http:port 获取来的 nodejs 在开启 inspect 的时候默认会启动一个 inspect server,其地址为 ​http:127.0.0.1:${inspect_port}​,其inspect_port默认为9229,当然也可以通过node --inspect-brk --port:${inspect_port}来指定其端口。 其暴露了一个接口 ​/json​,通过该接口即可获得其对应的 websocket 地址
img

下面我们来通过 vscode 来调试 js,首先创建一个 launch 任务,此时我们选择 Node.js: attach
img

我们选择通过 port 来 attach 到 js 上,配置如下

1
2
3
4
5
6
7
8
9
{
"type": "node",
"request": "attach",
"name": "node:attach",
"port": 9229, // 绑定到node.js默认的inspect的端口
"skipFiles": [
"<node_internals>/**"
]
},

此时我们只需要启动 lldb:node 启动调试,其会自动的停止在第一行 js 代码上。这样我们就实现了在 vscode 里混合调试 c++和 js

compound 模式

借助于 vscode 的 launch 的 compound 功能,我们甚至可以避免手动的切换 debugger,达到真正的一键调试,配置如下

1
2
3
4
5
6
"compounds": [
{
"name": "node_c++",
"configurations": ["lldb:node","node:attach"]
}
]

这样我们点击 node_c++功能就可以实现一键调试

pytorch库介绍

Pytorch autograd,backward 详解

https://zhuanlan.zhihu.com/p/83172023

Pytorch-view 的用法

https://zhuanlan.zhihu.com/p/87856193

pytorch 中 nn.Embedding 原理及使用

https://www.jianshu.com/p/63e7acc5e890

GRU 使用

https://zhuanlan.zhihu.com/p/37217734
https://www.jianshu.com/p/0c87b6ab0c4a

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
import torch.nn as nn
import torch

# gru = nn.GRU(input_size=50, hidden_size=50, batch_first=True)
# embed = nn.Embedding(3, 50)
# x = torch.LongTensor([[0, 1, 2]])
# x_embed = embed(x)
# out, hidden = gru(x_embed)


gru = nn.GRU(input_size=5, hidden_size=6,
num_layers=2, # gru层数
batch_first=False, # 默认参数 True:(batch, seq, feature) False:True:( seq,batch, feature),
bidirectional=False, # 默认参数
)

# N=batch size
# L=sequence length
# D=2 if bidirectional=True else 1
# Hin=input size
# Hout=outout size


input_ = torch.randn(1, 3, 5) # (L,N,hin)(序列长度,batch size大小,输入维度大小)
h0 = torch.randn(2 * 1, 3, 6) # (D∗num_layers,N,Hout)(是否双向乘以层数,batch size大小,输出维度大小)

output, hn = gru(input_, h0)
# output:[1, 3, 6] (L,N,D*Hout)=(1,3,1*6)
# hn:[2, 3, 6] (D*num_layers,N,Hout)(1*2,3,6)

print(output.shape, hn.shape)
# torch.Size([1, 3, 6]) torch.Size([2, 3, 6])

样例二
# 创建一个输入输入50维的GRU
gru = nn.GRU(input_size=50, hidden_size=50, batch_first=True)

# 创建一个字典大小为3,词向量维度为50维的Embedding。
embed = nn.Embedding(3, 50)

# 创建一个二维LongTensor索引数据(作为索引数据的时候一般都使用LongTensor)
x = torch.LongTensor([[0, 1, 2]]) # x.size() --> torch.Size([1, 3])

# 将索引映射到向量
x_embed = embed(x) # x_embed.size() --> torch.Size([1, 3, 50])

深度学习挑选变量

挑选变量的方法多种多样,可以用 IV、GBDT、随机逻辑回归、随机森林、逐步回归、cluster 等等(我在建模中实际用到)。

深度学习-概率知识

伯努利分布和二项式分布

https://blog.csdn.net/adczsw/article/details/118331225

雅克比矩阵

逻辑回归

https://cloud.tencent.com/developer/article/1694338

卷积神经网络

https://zhuanlan.zhihu.com/p/21930884

如何确定神经网络的层数和隐藏层神经元数量

https://zhuanlan.zhihu.com/p/100419971

激活函数

激活函数的主要作用是提供网络的非线性表达建模能力,想象一下如果没有激活函数,那么神经网络只能表达线性映射,此刻即便是有再多的隐藏层,其整个网络和单层的神经网络都是等价的。

RELU sigmod tanh

0-1(二元输出层) 用 sigmod
其他的偏向 RELU

首先使用 ReLU,速度最快,然后观察模型的表现。
如果 ReLU 效果不是很好,可以尝试 Leaky ReLU 或 Maxout 等变种。
尝试 tanh 正切函数(以零点为中心,零点处梯度为 1)。
在深度不是特别深的 CNN 中,激活函数的影响一般不会太大。
Kaggle 比赛,试试 Mish?

Back Propagation(梯度反向传播)实例讲解(经典必看)

https://zhuanlan.zhihu.com/p/40378224

拟合说明

过拟合:训练出的模型在测试集上 Loss 很小,在训练集上 Loss 较大
欠拟合:训练出的模型在测试集上 Loss 很大,在训练集上 Loss 也很大
拟合:训练的刚刚好,在测试集上 Loss 很小,在训练集上 Loss 也很小

梯度下降优化算法

  1. 运动梯度下降算法
  2. RMSprop
  3. Adam

Batch Normalization 原理与实战 (加快收敛)

https://zhuanlan.zhihu.com/p/34879333

transforms.Normalize

1
2
transform.ToTensor(),
transform.Normalize((0.5,0.5,0.5),(0.5,0.5,0.5))

那 transform.Normalize()是怎么工作的呢?以上面代码为例,ToTensor()能够把灰度范围从 0-255 变换到 0-1 之间,而后面的 transform.Normalize()则把 0-1 变换到(-1,1).具体地说,对每个通道而言,Normalize 执行以下操作:

image=(image-mean)/std

其中 mean 和 std 分别通过(0.5,0.5,0.5)和(0.5,0.5,0.5)进行指定。原来的 0-1 最小值 0 则变成(0-0.5)/0.5=-1,而最大值 1 则变成(1-0.5)/0.5=1

torch.nn.MaxPool2d 详解

https://blog.csdn.net/weixin_38481963/article/details/109962715

卷积数据输入说明

卷积输入输出是四维张量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import torch
import torch.nn as nn

# 仅定义一个 3x3 的池化层窗口
m = nn.MaxPool2d(kernel_size=(3, 3))

# 定义输入
# 四个参数分别表示 (batch_size, C_in, H_in, W_in)
# 分别对应,批处理大小,输入通道数,图像高度(像素),图像宽度(像素)
# 为了简化表示,我们只模拟单张图片输入,单通道图片,图片大小是6x6
input = torch.randn(1, 1, 6, 6)

print(input)

output = m(input)

print(output)

torch.nn.Linear() 详解

https://www.cnblogs.com/blairgrowing/p/15976598.html

One/zero-shot

One/zero-shot learning 都是用来进行学习分类的算法。One-shot learning 就是对某一/某些类别只提供一个或者少量的训练样本;http://vision.stanford.edu/documents/Fei-FeiFergusPerona2006.pdfZero-shot learning 顾名思义就是对某一/某些类别完全不提供训练样本。

Word Embedding(文本数据转换为数值型数据)

文本表示的类型:

基于 one-hot、tf-idf、textrank 等的 bag-of-words;
主题模型:LSA(SVD)、pLSA、LDA;
基于词向量的固定表征:word2vec、fastText、glove
基于词向量的动态表征:ELMO、GPT、bert

nn.Embedding 的用法和理解

https://blog.csdn.net/qq_39540454/article/details/115215056

docker命令介绍

mac 下,挂载 docker 容器日志

1
docker run -it -v /var/lib/docker/containers:/var/lib/docker/containers alpine sh /

chatgpt-intro

ModuleNotFoundError: No module named ‘html.parser’; ‘html’ is not a package

/Users/huangzhenzeng/Documents/ChatGpt/env/bin/python -m pip install –upgrade pip

ERROR: Can not execute setup.py since setuptools is not available in the build environment

pip install –upgrade setuptools

选房知识点

选房前,一定要踩点楼盘

朝向顺序

东南 -》西南 -》东北次选 -》 西北不要了

优先考虑点

通勤 -》教育 -》户型 -》朝向

考虑点

1.选南向看景的,不选南向靠路的 2.选择次楼王栋的,不选楼王栋的 3.有的选的情况下,不选有底商的 4.选靠路窄的,不选路宽的 5.选靠普通马路的,不选挨着高架的 6.选普通的景,不选楼前是儿童乐园区的 7.选小区中间的,不选挨着路边的

参考

深圳住建局 几个人才房 选房参考

  1. 深铁熙府项目选房结果公示:http://zjj.sz.gov.cn/ztfw/zfbz/fpjg/content/post_10500899.html
  2. 新城华苑项目选房结果公示:http://www.baoan.gov.cn/bajshej/gkmlpt/content/10/10507/post_10507490.html#5445

android更新apk方式

禁默安装

App 内升级调用 PackageInstaller

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
public static void installApk1(
final @NonNull File apkFile, final @NonNull PermissionsActivity permissionsActivity) {
String apkName = "appInstall.apk";
long apkFileLength = apkFile.length();

PackageManager pm = permissionsActivity.getPackageManager();
PackageInstaller packageInstaller = pm.getPackageInstaller();
packageInstaller.registerSessionCallback(new PackageInstaller.SessionCallback() {
@Override
public void onCreated(int sessionId) {
Log.e(TAG, "Install Start sessionId-> " + sessionId);
}

@Override
public void onBadgingChanged(int sessionId) {}

@Override
public void onActiveChanged(int sessionId, boolean active) {}

@Override
public void onProgressChanged(int sessionId, float progress) {}

@Override
public void onFinished(int sessionId, boolean success) {
if (success) {
Log.e(TAG, "Silent Install Success");
} else {
Log.e(TAG, "Silent Install Fail");
}
}
});

int count;
int sessionId;
byte[] buffer = new byte[65536];

InputStream inputStream;
OutputStream outputStream;
PackageInstaller.Session session = null;
PackageInstaller.SessionParams sessionParams;

try {
sessionParams = new PackageInstaller.SessionParams(PackageInstaller.SessionParams.MODE_FULL_INSTALL);
sessionId = packageInstaller.createSession(sessionParams);
session = packageInstaller.openSession(sessionId);

inputStream = new FileInputStream(apkFile);
outputStream = session.openWrite(apkName, 0, apkFileLength);

while((count = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, count);
float progress = ((float)count / (float)apkFileLength);
session.setStagingProgress(progress);
}
session.fsync(outputStream);

inputStream.close();
outputStream.flush();
outputStream.close();

Intent intent = new Intent();
intent.setAction("xinan.intent.action.APP_INSTALL");
PendingIntent pendingIntent = PendingIntent.getBroadcast(permissionsActivity.getBaseContext(), 0, intent, 0);
session.commit(pendingIntent.getIntentSender());
} catch (Exception e) {
e.printStackTrace();
if (session != null) {
session.abandon();
}
} finally {
}
}

注册系统服务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
public class AutoStartAppReceiver extends BroadcastReceiver {
private final String TAG = "AutoStartReceiver";
private final String ACTION_BOOT = "android.intent.action.BOOT_COMPLETED";
private final String ACTION_CUSTOM_BOOT = "xinan.intent.action.BOOT_COMPLETED";
private final String ACTION_CUSTOM_AFTER_SYSTEM_UI = "xinan.intent.action.AfterStartSystemUI";
private final String ACTION_APP_INSTALL = "xinan.intent.action.APP_INSTALL";

/**
* 接收广播消息后都会进入 onReceive 方法,然后要做的就是对相应的消息做出相应的处理
*
* @param context 表示广播接收器所运行的上下文
* @param intent 表示广播接收器收到的Intent
*/
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
Log.i(TAG, "onReceive:" + action);
if (ACTION_BOOT.equals(action)
|| ACTION_CUSTOM_AFTER_SYSTEM_UI.equals(action)
|| ACTION_CUSTOM_BOOT.equals(action)) {
launchApp(context);
} else if (ACTION_APP_INSTALL.equals(action)) {
Bundle extras = intent.getExtras();
int status = extras.getInt(PackageInstaller.EXTRA_STATUS);
String message = extras.getString(PackageInstaller.EXTRA_STATUS_MESSAGE);
Log.i(TAG, "onReceive status:" + status + " message:" + message);

switch (status) {
case PackageInstaller.STATUS_PENDING_USER_ACTION:
break;
case PackageInstaller.STATUS_SUCCESS:
Log.d(TAG, "Install succeeded!");
launchApp(context);
break;
case PackageInstaller.STATUS_FAILURE:
case PackageInstaller.STATUS_FAILURE_ABORTED:
case PackageInstaller.STATUS_FAILURE_BLOCKED:
case PackageInstaller.STATUS_FAILURE_CONFLICT:
case PackageInstaller.STATUS_FAILURE_INCOMPATIBLE:
case PackageInstaller.STATUS_FAILURE_INVALID:
case PackageInstaller.STATUS_FAILURE_STORAGE:
Log.e(TAG, "Install failed!" + status + ", " + message);
break;
default:
Log.e(TAG, "Unrecognized status received from installer: " + status);
}
}
}

private void launchApp(Context context) {
try {
String packageName = "com.xinan.ubox";
PackageManager pm = context.getPackageManager();
if (checkApp(pm, packageName)) {
if (!isRunning(context, packageName)) {
Log.i(TAG, "app start:" + packageName);
Intent intentMainActivity = pm.getLaunchIntentForPackage(packageName);
intentMainActivity.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intentMainActivity);
} else {
Log.i(TAG, "app is running:" + packageName);
}
} else {
Log.i(TAG, "app not exist:" + packageName);
}
} catch (Exception e) {
Log.i(TAG, "onReceive error:" + e.getLocalizedMessage());
}
}

private boolean checkApp(PackageManager pm, String packageName) {
try {
PackageInfo packageInfo = pm.getPackageInfo(packageName, 0);
return packageInfo != null;
} catch (Exception e) {
return false;
}
}

public boolean isRunning(Context context, String packageName) {
try {
ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
//获取当前所有存活task的信息
List<ActivityManager.RunningTaskInfo> processInfos = activityManager.getRunningTasks(Integer.MAX_VALUE);
//遍历,若task的name与当前task的name相同,则返回true,否则,返回false
for (ActivityManager.RunningTaskInfo process : processInfos) {
if (process.baseActivity.getPackageName().equals(packageName)
|| process.topActivity.getPackageName().equals(packageName)) {
return true;
}
}

return false;
} catch (Exception e) {
Log.i(TAG, "isRunning error:" + e.getLocalizedMessage());

return false;
}
}
}

manifest 注册接收器

1
2
3
4
5
6
7
8
9
10
11
12
13
<!--注册接收系统开机广播消息的广播接收者-->
<receiver
android:name=".AutoStartAppReceiver"
android:enabled="true"
android:exported="true">
<intent-filter android:priority="1000">
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="xinan.intent.action.AfterStartSystemUI" />
<action android:name="xinan.intent.action.APP_INSTALL" />
<action android:name="xinan.intent.action.BOOT_COMPLETED" />
<category android:name="android.intent.category.HOME" />
</intent-filter>
</receiver>

参考资料

https://blog.csdn.net/sinat_35622297/article/details/83995957?spm=1001.2101.3001.6650.11&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-11-83995957-blog-128485823.235%5Ev27%5Epc_relevant_multi_platform_whitelistv3&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-11-83995957-blog-128485823.235%5Ev27%5Epc_relevant_multi_platform_whitelistv3&utm_relevant_index=17

https://stackoverflow.com/questions/58085899/android-10-no-activity-found-to-handle-intent

https://zhuanlan.zhihu.com/p/183960413

https://android.googlesource.com/platform/development/+/master/samples/ApiDemos/src/com/example/android/apis/content/InstallApkSessionApi.java