2024年4月

前言:

最近的 Taurus.MVC 版本,对性能这一块有了不少优化,因此准备进行一下压测,来测试并记录一下 Taurus.MVC 框架的性能,以便后续持续优化改进。

今天先压测 .NET Core 版本,后续有时间再压测一下.NET 版本。

下面来看不同场景下的压测结果,以下测试结果会由两台电脑进行分别测试。

一、旧电脑环境:

CPU :Intel(R) Core(TM) i5-9400 CPU @ 2.90GHz内核:6逻辑处理器:6
内存:16G

程序在 .NET8 编绎,以 Kestrel 为主机直接运行在 Window 环境:

1、测试 Window 11 下,单机ab工具压测:

由于ab工具占用资源不多,发起的并发能力也有限,先用它进行本机压测,试试水。

ab的版本信息:

A、先测试单线程的运行性能(简单接口返回,控制台带日志输出):

ab -n 100000 -c 1 http://192.168.100.102:51996/api/hello

测试结果:并发数1,qps =  3263

Server Software:
Server Hostname:
192.168.100.102Server Port:51996Document Path:/api/hello
Document Length:
24bytes

Concurrency Level:
1Time takenfor tests: 30.641seconds
Complete requests:
100000Failed requests:0Write errors:0Total transferred:13900000bytes
HTML transferred:
2400000bytes
Requests per second:
3263.63 [#/sec] (mean)
Time per request:
0.306[ms] (mean)
Time per request:
0.306[ms] (mean, across all concurrent requests)
Transfer rate:
443.01 [Kbytes/sec] received

看一下程序运行的时间:

从程序打印的日志上看,接口执行时间仅有0.03毫秒,理论值单线程压测是可以达到1000/0.0345= 28089,

去掉控制器日志输出,还能再提升1下,再配置个64核cpu,就是传说中的轻轻松松的单机百万qps了。

B、我们调整一下参数,看看ab在单机下能压出多少来(简单接口返回,控制台带日志输出):

ab -n 100000 -c 2 http://192.168.100.102:51996/api/hello

测试结果:

Concurrency Level:      2Time takenfor tests:   18.187seconds
Complete requests:
100000Failed requests:0Write errors:0Total transferred:13900000bytes
HTML transferred:
2400000bytes
Requests per second:
5498.28 [#/sec] (mean)
Time per request:
0.364[ms] (mean)
Time per request:
0.182[ms] (mean, across all concurrent requests)
Transfer rate:
746.35 [Kbytes/sec] received

没办法,只能压 2 个并发链接,CPU 跑满了,程序占40%多,ab也占了40%多,说好的ab不吃资源的,直接cpu拉走一半,呵呵。

C、我们关闭日志输出,重新看看上面的两个能测试出多少(简单接口返回,控制台无日志输出):

我们添加以下代码,关闭 Kestrel 默认的控制台信息输出:

services.AddLogging(op => op.SetMinimumLevel(LogLevel.None));

【后续的测试,都保持控制器日志关闭】

重新编绎后,进行重新测试:

测试结果:并发数1,qps = 3595

Concurrency Level:      1Time takenfor tests:   2.781seconds
Complete requests:
10000Failed requests:0Write errors:0Total transferred:1390000bytes
HTML transferred:
240000bytes
Requests per second:
3595.51 [#/sec] (mean)
Time per request:
0.278[ms] (mean)
Time per request:
0.278[ms] (mean, across all concurrent requests)
Transfer rate:
488.06 [Kbytes/sec] received

关闭日志,提升了300多,后续测试,将会保持控制台日志的关闭。

测试结果:并发数 2,qps = 5765

Concurrency Level:      2Time takenfor tests:   1.734seconds
Complete requests:
10000Failed requests:0Write errors:0Total transferred:1390000bytes
HTML transferred:
240000bytes
Requests per second:
5765.77 [#/sec] (mean)
Time per request:
0.347[ms] (mean)
Time per request:
0.173[ms] (mean, across all concurrent requests)
Transfer rate:
782.66 [Kbytes/sec] received

接下来,我们将接口调整一下,单纯的返回 Hello World 没啥看头,改成常规一些。

D、使用 CYQ.Data 读数据库,输出 Json,来看看压测结果(读数据库接口,控制台无日志输出)

测试代码:

public void Hello(stringmsg)
{
string conn = "server=.;database=MSLog;uid=sa;pwd=123456";using (MProc proc = new MProc("select top 1 * from SysLogs", conn))
{
Write(proc.ExeJson());
}
}

运行结果:返回一条数据:

下面直接进行压测结果:并发数 2 ,qps = 5470,和未关闭日志输出时差不多。

Concurrency Level:      2Time takenfor tests:   1.828seconds
Complete requests:
10000Failed requests:0Write errors:0Total transferred:10810000bytes
HTML transferred:
9590000bytes
Requests per second:
5470.23 [#/sec] (mean)
Time per request:
0.366[ms] (mean)
Time per request:
0.183[ms] (mean, across all concurrent requests)
Transfer rate:
5774.73 [Kbytes/sec] received

小结:

从上面的测试结果,观察CPU中可以看出,ab 这个工具,吃 cpu 资源不说,其并发数量也有限。

下面更换 wrk 进行测试,由于 wrk 只能在 linux 中运行,因此在本机上,开启了虚拟机。

2、测试 Window 11 下,虚拟机wrk工具压测:(读数据库输出,控制台无日志输出)

虚拟机环境:

CPU :Intel(R) Core(TM) i5-9400 CPU @ 2.90GHz
内核:
2逻辑处理器:2内存:4G

分完虚拟机后,本机就剩下 4 核了,再去掉打开任务管理器,就占掉了10%的cpu,我了个去,当个3核用了。

不过问题不大,尽管测就是了,为了保持接口的通用性,继续使用读数据库输出 Json 的接口:

先使用1线程1并发测试试试水:

 wrk -t 1 -c1 -d 10s http://192.168.100.102:51996/api/hello

测试结果:qps = 1518

Running 10s test @ http://192.168.100.102:51996/api/hello
  1 threads and 1connections
Thread Stats Avg Stdev Max
+/-Stdev
Latency
2.76ms 14.97ms 200.26ms 98.45%Req/Sec 1.54k 402.67 2.62k 73.74% 15294 requests in 10.07s, 16.07MB read
Requests
/sec: 1518.47Transfer/sec: 1.60MB

测试过程,通过虚拟机(top 指令)和Windows(任务管理器)观察 cpu,发现没怎么动,看来 wrk 要跑满性能,得加量。

我们给虚拟机分了2个核,不能浪费,要跑满它,于是不断调整参数:

wrk -t 2 -c4096 -d 10s http://192.168.100.102:51996/api/hello

测试结果:qps = 23303

Running 10s test @ http://192.168.100.102:51996/api/hello
  2 threads and 4096connections
Thread Stats Avg Stdev Max
+/-Stdev
Latency
28.17ms 19.27ms 307.26ms 82.72%Req/Sec 11.63k 12.33k 37.01k 77.53% 234427 requests in 10.06s, 246.37MB read
Socket errors: connect
3077, read 0, write 0, timeout 0Requests/sec: 23303.58Transfer/sec: 24.49MB

从测试结果观察,wrk 更能压测出性能的极限,当然,这是 wrk 的极限,不是程序的极限。

因为整个压测过程,程序只占了30%左右的cpu,但没办法,cpu 让其它资源给吃光了。

我们知道,.NET Core 的程序,跑在 Linux 下,能会有更优的性能,不过不急先。

由于本机资源有限,干扰程序较多,这里打算拿出我的新电脑,来进行重新测试,看看程序在新电脑的表现如何。

二、新电脑环境:

CPU    13th Gen Intel(R) Core(TM) i5-13600KF内核:14逻辑处理器:20内存:64G

接下来,我们看看新电脑的表现如何,使用一样的程序:

1、测试 Window 11 下,单机ab工具压测:

A、先测试单线程的运行性能(简单接口返回,控制台无日志输出):

ab -n 100000 -c 1 http://192.168.100.102:51996/api/hello

测试结果:并发数1,qps =  11389

Concurrency Level:      1Time takenfor tests:   0.878seconds
Complete requests:
10000Failed requests:0Write errors:0Total transferred:1410000bytes
HTML transferred:
260000bytes
Requests per second:
11389.76 [#/sec] (mean)
Time per request:
0.088[ms] (mean)
Time per request:
0.088[ms] (mean, across all concurrent requests)
Transfer rate:
1568.32 [Kbytes/sec] received

B、我们调整一下参数,看看ab在单机下能压出多少来(简单接口返回,控制台无日志输出):

ab -n 100000 -c 4 http://192.168.100.101:51996/api/hello

测试结果:并发数4,qps = 18247

Concurrency Level:      4Time takenfor tests:   5.480seconds
Complete requests:
100000Failed requests:0Write errors:0Total transferred:14100000bytes
HTML transferred:
2600000bytes
Requests per second:
18247.09 [#/sec] (mean)
Time per request:
0.219[ms] (mean)
Time per request:
0.055[ms] (mean, across all concurrent requests)
Transfer rate:
2512.54 [Kbytes/sec] received

看来 ab 不行啊,压不出结果,程序的cpu才跑了不到2%。

小结:

虽然 ab 压测不够力,但从单线程的测试结果可以看出,新电脑的cpu运行效率是旧电脑性能的3倍左右,效率拉满。

以此看出,平时在采购云服务器时,也得顺带关注一下CPU的型号,好的型号,能提升运行效率,提高并发。

2、测试 Window 11 下,虚拟机wrk工具压测:(简单接口,控制台无日志输出)

虚拟机环境:

CPU    13th Gen Intel(R) Core(TM) i5-13600KF内核:    2逻辑处理器: 2内存:4G

先给虚拟机2核,本机剩下 12 核了,可以好好压一下了。

wrk -t 1 -c 1 -d 10s http://192.168.100.101:51996/api/hello

测试结果:1并发,qps = 14084

Running 10s test @ http://192.168.100.101:51996/api/hello
  1 threads and 1connections
Thread Stats Avg Stdev Max
+/-Stdev
Latency
6.43ms 29.09ms 218.31ms 95.10%Req/Sec 14.43k 3.27k 17.98k 91.84% 141377 requests in 10.04s, 21.71MB read
Requests
/sec: 14084.98Transfer/sec: 2.16MB

和 ab 一样,一个链接并发压不出什么效果,加大效果看看。

wrk -t 8 -c 2048 -d 10s http://192.168.100.101:51996/api/hello

测试结果:qps = 84306

Running 10s test @ http://192.168.100.101:51996/api/hello
  28 threads and 2048connections
Thread Stats Avg Stdev Max
+/-Stdev
Latency
11.40ms 10.81ms 222.31ms 86.60%Req/Sec 5.35k 3.03k 18.81k 69.09% 850042 requests in 10.08s, 130.52MB read
Socket errors: connect
1051, read 0, write 100, timeout 0Requests/sec: 84306.38Transfer/sec: 12.94MB

压测试过程,观察两个cpu,虚拟机(110%-130%,2核还没跑满),程序只跑16%-20%,整体40-50%左右,感觉还能往上跑。

估计是压力不够,试着分给虚拟机多2核,看看有没有效果。

虚拟机环境:

CPU    13th Gen Intel(R) Core(TM) i5-13600KF
内核:    4
逻辑处理器: 4
内存:8G

继续压测试:

wrk -t18 -c 1400 -d 60s http://192.168.100.101:51996/api/hello

测试结果:qps = 105462

Running 1m test @ http://192.168.100.101:51996/api/hello
  18 threads and 1400connections
Thread Stats Avg Stdev Max
+/-Stdev
Latency
10.02ms 10.05ms 267.70ms 90.26%Req/Sec 6.68k 3.31k 17.16k 62.65% 6339226 requests in 1.00m, 0.95GB read
Socket errors: connect
383, read 0, write 25, timeout 0Requests/sec: 105462.01Transfer/sec: 16.19MB

之前压测时间在10s-20s,qps 都在9万多,把压测时间拉长到1分钟,超过了10万了。

看来把压测时间拉长,qps 会高一点。

测试过程中,虚拟机CPU(在180%左右,给了4核,也不顶用,没能跑满),程序占用CPU(20%左右)。

还是跑不满,没办法,压力上不去了,只好换个口味测试。

重新压测 CYQ.Data 读数据库转Json输出的接口(数据库mssql2012 安装在Window 11 本机):

接口的调用输出:

进行压测:

wrk -t18 -c 1200 -d 60s http://192.168.100.101:51996/api/hellodb

测试结果:qps = 73122

Running 1m test @ http://192.168.100.101:51996/api/hellodb
  18 threads and 1200connections
Thread Stats Avg Stdev Max
+/-Stdev
Latency
47.62ms 86.25ms 1.15s 85.85%Req/Sec 4.61k 2.10k 17.56k 68.95% 4394613 requests in 1.00m, 4.51GB read
Socket errors: connect
185, read 0, write 24, timeout 1Requests/sec: 73122.19Transfer/sec: 76.85MB

再换一个,直接压 MVC 界面,看看效果。

这是压测试的 Taurus.MVC 的主界面:

修改压测路径:

wrk -t18 -c 1200 -d 60s http://192.168.100.101:51996/home/index

测试结果:qps = 39349

Running 1m test @ http://192.168.100.101:51996/home/index
  18 threads and 1200connections
Thread Stats Avg Stdev Max
+/-Stdev
Latency
82.78ms 160.41ms 1.94s 87.98%Req/Sec 2.33k 0.94k 7.67k 67.93% 2364614 requests in 1.00m, 8.75GB read
Socket errors: connect
185, read 0, write 0, timeout 918Requests/sec: 39349.00Transfer/sec: 149.13MB

这时候观察,虽然取得了不错的结果,但 CPU 跑满100%了,也有918个超时,看来呈现的加载与呈现,很消耗计算量。

到了最后的步骤了,.NET Core 程序,还是得放到 Linux 系统下跑看看效果 ,复制一台虚拟机,用来部署 .NET Core 程序。

3、测试 CentOS 7 下,虚拟机 wrk 工具压测:

新的虚拟机环境:

CPU    13th Gen Intel(R) Core(TM) i5-13600KF
内核:    8
逻辑处理器: 8
内存:8G

1、测试接口:直接压测 CYQ.Data 读数据库转Json输出的接口(数据库mssql2012安装在Window 11 系统):

wrk -t18 -c 1600 -d 60s http://192.168.100.666666:51996/api/hellodb

测试结果:qps = 80831

Running 1m test @ http://192.168.100.666666:51996/api/hellodb
  18 threads and 1600connections
Thread Stats Avg Stdev Max
+/-Stdev
Latency
35.63ms 74.47ms 1.03s 87.97%Req/Sec 4.83k 2.67k 18.55k 69.03% 4856997 requests in 1.00m, 4.98GB read
Socket errors: connect
581, read 0, write 0, timeout 0Requests/sec: 80831.35Transfer/sec: 84.95MB

观察CPU:压测虚拟机(130%左右,用了1.3个核左右),应用程序虚拟机(450%左右,用了4.5个核左右)

2、测试接口:直接测试简单接口

wrk -t18 -c 1600 -d 60s http://192.168.100.666666:51996/api/hello

测试结果:qps = 105994

Running 1m test @ http://192.168.100.666666:51996/api/hello
  18 threads and 1600connections
Thread Stats Avg Stdev Max
+/-Stdev
Latency
9.16ms 4.84ms 212.60ms 79.65%Req/Sec 6.32k 3.65k 27.06k 57.03% 6424281 requests in 1.00m, 0.95GB read
Socket errors: connect
581, read 0, write 0, timeout 0Requests/sec: 106908.28Transfer/sec: 16.21MB

观察CPU:和上一个结果差不多,只用了虚拟机的50%左右,就是部署在Linux 上,随便调整参数,都轻松10万+。

总结:

对于 API 压测:

旧电脑轻松就打满CPU,主要是被ab和其它应用吃了资源,所以压测上不去,去掉虚拟机两核后,在读数据库转Json输出的情况下,压出了2万3的qps。

新电脑上限太高,wrk 都压不住,上10万+了,CPU也才20%左右,可见一个高效的CPU对并发的提升是多么明显。

新电脑在读数据库转Json输出的情况下,也有8万+的qps,这个3倍左右的效率,明显的有点明显了。

最后部署在 Linux,可以感觉性能明显比 Window 运行高一些,Window 需要小小调优参数才10万+,而 Linux 上随便调都10万+。

但因wrk给的压力也有限,10万+后无法再测试了,听说 ulimit -n 命令可以解锁,发起更大的并发,这个下次再试了。

对于 MVC 压测:

明显感觉 MVC 的计算量大了很多,wrk 提供的压力已足够跑满CPU,极限跑出近4万的qps,感觉后续应该还能小优化一下。

整体来说,今天的压力测试结果,除了压测试MVC界面,CPU 压满了,而压测试API,CPU 都没能跑满整机的30%,心累啊,先就到这里了。

附本文的运行程序:
TaurusMVC运行程序下载
- 解压后可直接运行 Taurus.View.exe,欢迎下载自行测试【需要.NET 8 运行环境】


正常使用表格

很简单,使用一次就知道了,不过多介绍。

// 创建 JTable 实例,使用默认的模型
JTable table = new JTable();

// 设置表格数据
Object[][] data = {
	{1, "Apple", 10.0},
	{2, "Banana", 5.0},
	{3, "Orange", 8.0}
};

Object[] columnNames = {"ID", "Name", "Price"};
table.setModel(new DefaultTableModel(data, columnNames));

show:
image

自定义表格样式

// 创建 JTable 实例,并使用自定义的 FileTableModel
JTable table = new JTable(new FileTableModel());

// 获取第二列(列索引为 1)的列模型 . 为第二列设置自定义的渲染器 AvailableRenderer
table.getColumnModel().getColumn(1).setCellRenderer(new AvailableRenderer());

// 获取第二列(列索引为 1)的列模型 . 为第二列设置自定义的编辑器 AvailableEditor . 将一个 JCheckBox 实例作为编辑器的渲染组件传入
table.getColumnModel().getColumn(1).setCellEditor(new AvailableEditor(new JCheckBox()));

可以看到,将默认的Model替换,改成自定义的模型,然后设置渲染器和编辑。渲染器就类似HTML的CSS样式。 编辑器就类似JS,可以在里面编辑事件,方便与用户交互。

核心就是理解这三个类的各自作用:

  • FileTableModel 定义了表格的数据源和基本行为。
  • AvailableRenderer 定义了表格中复选框单元格的显示效果。
  • AvailableEditor 定义了表格中复选框单元格的编辑交互行为。

Model、渲染器和编辑器的代码:

// 定义表格模型
// FileTableModel 继承自 AbstractTableModel,用于自定义表格模型
private class FileTableModel extends AbstractTableModel {
	@Override
	public int getRowCount() {
		// 返回表格中的行数,通过获取 data 数组的长度
		return data.length;
	}

	@Override
	public int getColumnCount() {
		// 返回表格中的列数,通过获取 columnNames 数组的长度
		return columnNames.length;
	}

	@Override
	public Object getValueAt(int rowIndex, int columnIndex) {
		// 返回指定单元格的值,通过访问 data 数组中相应的位置
		return data[rowIndex][columnIndex];
	}

	@Override
	public String getColumnName(int column) {
		// 返回指定列的列名,通过访问 columnNames 数组中相应的位置
		return columnNames[column];
	}

	@Override
	public Class<?> getColumnClass(int columnIndex) {
		// 指定哪些单元格可以编辑,这里设置只有第二列(columnIndex == 1)可以编辑
		return getValueAt(0, columnIndex).getClass();
	}

	@Override
	public boolean isCellEditable(int rowIndex, int columnIndex) {
		// 指定哪些单元格可以编辑,这里设置只有第二列(columnIndex == 1)可以编辑
		return columnIndex == 1;
	}

	@Override
	public void setValueAt(Object value, int rowIndex, int columnIndex) {
		// 设置指定单元格的值,并通知表格该单元格数据已经更新
		data[rowIndex][columnIndex] = value;
		fireTableCellUpdated(rowIndex, columnIndex);
	}
}

// 定义渲染器,用于渲染第二列的复选框
// AvailableRenderer 是一个自定义的渲染器,用于渲染 JTable 中的复选框单元格
// 它继承自 JCheckBox 并实现 TableCellRenderer 接口
private class AvailableRenderer extends JCheckBox implements TableCellRenderer {

	// 构造函数,用于初始化渲染器
	public AvailableRenderer() {
		// 设置复选框在单元格中水平居中
		setHorizontalAlignment(SwingConstants.CENTER);
	}

	// 重写此方法,用于自定义渲染单元格的行为
	@Override
	public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
		// 根据传入的值设置复选框的选中状态
		setSelected((Boolean) value);

		// 将复选框设置为可用状态,以便能够正确渲染
		setEnabled(true);

		// 根据当前单元格是否被选中,设置复选框的背景色
		// 如果被选中,则使用表格的选中行背景色
		// 否则使用表格的默认背景色
		setBackground(isSelected ? table.getSelectionBackground() : table.getBackground());

		// 返回当前 JCheckBox 实例,作为渲染的组件
		return this;
	}
}


// 定义编辑器,用于编辑第二列的复选框
private class AvailableEditor extends DefaultCellEditor implements ItemListener {
	private JCheckBox checkBox;
	private int editingRow;

	public AvailableEditor(JCheckBox checkBox) {
		super(checkBox);
		this.checkBox = checkBox;
		this.checkBox.addItemListener(this);
	}

	@Override
	public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
		editingRow = row; // 记录当前编辑的行号
		checkBox.setSelected((Boolean) value);
		return checkBox;
	}

	@Override
	public Object getCellEditorValue() {
		return checkBox.isSelected();
	}

	@Override
	public void itemStateChanged(ItemEvent e) {
		super.fireEditingStopped();
		System.out.println("-----");  // 打印"123"

		int id = (int) data[editingRow][0]; // 获取ID
		String fileName = (String) data[editingRow][2]; // 获取文件名
		System.out.println("ID: " + id + ", File Name: " + fileName);
	}
}

shwo:
image

PrimiHub
一款由密码学专家团队打造的开源隐私计算平台,专注于分享数据安全、密码学、联邦学习、同态加密等隐私计算领域的技术和内容。

联邦学习中的差分隐私与同态加密

随着数据的爆炸式增长和对个人隐私保护意识的提高,隐私保护在机器学习领域中变得愈发重要。联邦学习作为一种分散式机器学习框架,允许多个参与方在不共享原始数据的情况下进行模型训练,因此成为保护隐私的一种重要方法。近年来,差分隐私和同态加密这两种隐私保护技术逐渐被引入到联邦学习中,并被认为是提高模型训练过程中隐私保护水平的有效手段。

差分隐私与同态加密的简介

差分隐私

差分隐私(Differential Privacy)是一种在保护个人隐私的同时,允许从数据中提取有用信息的方法。其核心思想是通过向数据引入控制的噪声来防止对个别数据的过度依赖从而泄露个人隐私。具体而言,对于任何一个单个个体的数据,差分隐私保证在算法输出中对该单个个体的贡献微乎其微,从而保护了个人隐私。

同态加密

同态加密(Homomorphic Encryption)是一种特殊的加密技术,允许在密文状态下执行计算,并在结果解密后与在明文状态下执行相同的计算得到相同的结果。这种特性使得数据在加密的状态下仍然可以进行计算,而不需要解密原始数据,从而保护了数据的隐私性。

联邦学习中的挑战与需求

在联邦学习中,参与方通常拥有不同的数据集,这些数据可能涵盖不同的特征和分布。因此,在模型训练过程中需要解决以下两个主要挑战:

  1. 隐私保护
    :参与方的数据可能包含敏感信息,如个人身份、健康记录等。在模型训练过程中,需要确保这些信息不被泄露。

  2. 模型集成
    :各参与方的数据集可能存在不同的特征分布,因此需要在模型训练过程中有效地整合这些分布差异,以保证模型的泛化性能。

差分隐私和同态加密技术可以分别应对上述挑战:

  • 差分隐私
    :通过在参与方的数据中引入噪声,可以有效地防止个别数据的泄露,从而保护隐私。在联邦学习中,差分隐私可以用于在模型训练过程中向梯度或模型参数中添加噪声,以保护个体数据的隐私。

  • 同态加密
    :同态加密可以在不暴露原始数据的情况下进行计算,因此可以在联邦学习中用于在密文状态下对模型参数进行计算。这种方式可以确保参与方的数据在整个训练过程中始终处于加密状态,从而保护隐私。

graph TD
A[原始数据集] --> B{差分隐私}
B -->|是| C[添加噪声]
B -->|否| D{同态加密}
D -->|是| E[加密数据]
D -->|否| F[计算]
E --> F
F --> G[模型训练]
G --> H[保护隐私]
H --> I[发布模型]

结合差分隐私和同态加密的优势

将差分隐私和同态加密结合到联邦学习中,可以获得以下几个优势:

  1. 双重保护
    :差分隐私和同态加密提供了双重保护,有效地保护了参与方的隐私信息。差分隐私通过添加噪声保护了数据的隐私,而同态加密则确保了数据在计算过程中的安全性。

  2. 灵活性
    :结合差分隐私和同态加密可以在保护隐私的同时保持数据的可用性和计算的有效性。差分隐私提供了在梯度计算中引入噪声的方式,而同态加密则允许在密文状态下进行计算,从而使得模型训练过程更加灵活。

  3. 更强的隐私保护
    :差分隐私和同态加密相互补充,可以提供比单独使用任何一种技术更强的隐私保护。结合两者可以有效地防止潜在的隐私泄露,保护个人数据的隐私。

差分隐私和同态加密作为两种主要的隐私保护技术,可以有效地应用于联邦学习中,提高模型训练过程中的隐私保护水平。它们的结合为联邦学习提供了双重保护,并在保护隐私的同时保持了数据的可用性和计算的有效性。随着隐私保护需求的不断增加,差分隐私和同态加密技术的发展将在联邦学习中发挥越来越重要的作用。

PrimiHub
一款由密码学专家团队打造的开源隐私计算平台,专注于分享数据安全、密码学、联邦学习、同态加密等隐私计算领域的技术和内容。

阿里巴巴最近开源了一个320亿参数的大语言模型Qwen1.5-32B,网上都说很强很强,那么它到底强在哪里呢?

更高的性价比

Qwen1.5-32B中的B是billion的意思,也就是10亿,32B就代表320亿参数量。

阿里之前还开源过一个大模型Qwen-1.5-72B,72B就代表720亿参数量。

相比之前开源的Qwen-1.5-72B,Qwen1.5-32B参数少了一多半,但是测试表现并没有相差多少。

大语言模型文件中的主要内容就是参数,参数少了一半,模型的文件大小也会小一半,那么加载到显存时占用的空间也会小一半。大家可能都知道现在显卡比较紧俏,我特地到京东查了一下,消费级的3090在8K左右,4090已经飙升到了1.5个W左右。

显存占用小一半就可以使用更少数量的显卡或者更低显存的显卡,这无疑会节省很多成本,而且模型的表现相比之前的大块头也没有多少明显的损失,所以用户能获得更高的性价比。

性能测试优良

上边提到Qwen1.5-32B的性能测试表现还不错,那么这个不错到底表现在哪里呢?

这里我找到一张测试结果的图表:

之前我看这些图表时都比较懵逼,主要就看谁的分数高,分高就是好,但是具体好在哪里也说不清楚。

这次我特地去查询了这些指标代表的含义,总算是搞明白了,特别分享给大家。

这些分数对应的每一列都是一个数据集,所谓数据集就是一些问题的集合,用它们来考察大模型应对各种问题的处理能力。这些数据集通常是知名大语言模型研究机构发布的,比较权威。

  • MMLU
    (Massive Multitask Language Understanding): 多领域知识理解,考察的是综合能力。涵盖57个不同领域的多项选择题,包括历史、文学、科学、工程技术等多个学科。使用这个数据集能评估模型的泛化能力,就是用它解决没有训练过的问题,或者说新问题,看看它的表现如何。
  • CMMLU
    :
    中文场景的多领域知识理解。由MBZUAI、上海交通大学、微软亚洲研究院共同推出,包含67个主题,涉及自然科学、社会科学、工程、人文以及常识等,专门用于评估语言模型在中文语境下的知识和推理能力。
  • C-Eval
    :
    中文能力评估。由上海交通大学、清华大学和爱丁堡大学的研究人员在2023年5月联合推出。包含13948个多项选择题,涵盖了52个不同的学科和四个难度级别。
  • GSM8K
    (Google's Standard Math Dataset 8K): 解决数学问题的能力。Google开发的一个数学问题求解数据集,包含大约8,000个高中到大学水平的数学问题。
  • MATH
    :
    解决数学问题的能力,类似于GSM8K。包含初等代数,代数,数论,计数和概率,几何,中等代数和微积分等领域的多种数学问题,用LaTeX格式编写。
  • MBPP
    (Mathematics Benchmarks for Pretrained Models): 数学推理和问题解决能力。包含一系列需要模型生成数学表达式或文字解答的数学问题。
  • HumanEval
    :
    编程能力。由OpenAI创建,专为评估代码生成模型的有效性。包含数百个编程题目及其解决方案。
  • BBH
    (Big-Bench Hard): 复杂语言理解能力。由Google、斯坦福等研究人员开发的数据集,包含大量复杂语言理解任务的集合,可能包含需要深度推理、常识运用或复杂认知技能的任务。

有了对这几个指标的理解,我们可以看到Qwen1.5-32B和Qwen1.5-72B的能力相差无几,在理解复杂语言的能力上还略胜一筹,不知道是不是学习了百度弱智吧的问题。

在这个对比图表上还有几个模型,我特别介绍下:

  • Llama2-34B

    Llama是Meta公司(也就是facebook)开源的一个大预言模型,有了Llama的开源,才有了国内大模型的百花齐放,否则大家还得摸索一阵。不过从这张图表上可以看出,Llama的这个模型已经落后了,普遍落后于其他模型,真是青出于蓝而胜于蓝。
  • Yi-34B

    这个据称是自研成功的开源大语言模型,也是在Llama开源后推出的,自然是借鉴了Llama,只不过不清楚借鉴了多少。这个模型是李开复老师投资的零一万物开发出来的,也是300多亿的参数,综合能力还不错,只是数学能力和解决复杂问题的能力比Qwen差一点。
  • Mixtral-8x7B

    一款高质量的稀疏专家混合模型,是一个欧洲公司开发的。这里的混合模型说的是其内部有多个子模型,比如有的擅长数学,有的擅长法语,有的擅长代码生成,等等。在生成Token时,Mixtral-8x7B会选择两个内部的专家子模型进行生成,每个专家子模型的参数是6B,所以它会比普通的300亿参数处理的更快。从图表对比可以看出其在数学和编程方面的能力还是挺不错的。

很多同学对国内大语言模型与GPT的差距也比较关心,我找到了一个Qwen1.5-72B和GPT-4的能力对比图,如下所示,可以看到差距还是很明显的,在数学、编程、复杂问题处理等方面都有着很大的提升空间。当然我们一直在追赶,只是别人也在进步,有人说这个差距是1年,也有人说是2年,你怎么看呢?

实测体验

指标上的表现并不能代表全部,我们用最近热议的“弱智吧”问题来测试一下。

“弱智吧”是一个百度贴吧,里边充满荒谬、离奇、不合常理的发言,研究者发现使用这里边的问题训练大语言模型能获得比较好的逻辑能力。

这里使用的工具是我在AutoDL上分享的一个镜像实例,这个镜像基于开源项目 text-generation webui,在这个webui中可以体验多种大语言模型。

创建实例

如果你也想实际测试一下,可以按照下面的步骤创建一个容器实例。

首先注册一个账号,AutoDL的访问地址:
https://www.autodl.com

创建实例时:地区选择“西北B区”,网络比较稳定;因为镜像安装的大模型需要24G显存,所以显卡需要选择3090或者4090;GPU数量只需要1个就能跑起来。

镜像选择“社区镜像”,输入 yinghuoai-text-generation-webui ,即可找到这个镜像。

实例启动后,在服务器实例列表中点击“JupyterLab”,进入一个Web页面。

在JupyterLab页面中打开“启动器”,这个镜像会安装3个大模型,默认启动的是Qwen-32B,这实际上是一个4bit的量化模型,只需要24G的显存就能跑起来,但是相比原版的32B性能略有下降,不过也够用了。原版的32B需要数倍的显存,AutoDL上跑起来成本太高。

启动成功后,我们可以看到一个Gradio的链接,点击就会在浏览器打开 text-generation-webui。

另外 text-generation-webui 还支持通过API访问大模型,API定义兼容OpenAI协议,有兴趣的可以体验下。

体验Qwen-32B

进入后需要先设置一下角色,在参数(Parameters)页签中,选择“AI助理”。这个AI助理是我创建的,方便进行中文对话。

在聊天(Chat)页签的右侧,有一个“Mode”,定义了大模型处理提示词的模式,需要选择“chat-instruct”。

然后我们就可以和它聊天了,如下是弱智吧的3个经典问题。可以看到,只有“生鱼片是死鱼片”这个问题回答的不太好,大模型好像不太能理解生鱼片的生到底是什么意思。

正常应该怎么回答呢?我先到阿里的“通义千问”上问了一下,感觉也没太能回答到点上,毕竟师出同门,训练用的语料应该都差不多。

然后我又找了一个GPT-4的应用问了一下。GPT-4倒是准确把握住了“生”和“死”的含义,只是它回答的不是那么直接,大家看图片中的内容吧。

在测试数据集的评测中,Qwen1.5-32B的中文处理能力是明显高于GPT-4的,但是“生鱼片是死鱼片”这个问题的确没有回答好,这是模型的泛化能力不足,还是训练语料的问题呢?对于这个问题,你怎么看?

模型下载

Huggingface
:

https://huggingface.co/Qwen

Huggingface镜像站:

https://hf-mirror.com/Qwen

AI快站:

https://aifasthub.com/models/Qwen


以上就是本文的主要内容。

MSBuild 是 .NET 开发体验的基本组成部分,但它对新手和有经验的开发人员都具有挑战性。为了帮助开发人员更好地理解他们的项目文件,并访问需要直接编辑项目文件的高级功能,我们发布了一个实验性的 MSBuild 编辑器,它对 MSBuild 文件的理解比当前 XML schema 所允许的要丰富得多。根据反馈,我们希望所有 .NET 开发人员都可以默认使用它。如果您使用 MSBuild 文件工作,请尝试一下,让我们知道它是如何工作的。

适合哪些用户使用?

尽管 Visual Studio 为管理项目及其设置提供了丰富的 UI,但您可能需要直接编辑 csproj 文件以访问 UI 中未公开的某些高级特性。在从源代码控制合并更改时,您可能还需要直接编辑 csproj 文件,或者您可能正在编写 targets 和 props 文件以供本地使用或在 NuGet 包中发布。如果这些场景中的任何一个适用于您,那么我们希望您体验下新功能。

了解您的项目文件

新的 MSBuild 编辑器不仅为 MSBuild 文件中的 XML 元素提供了快速信息,还为 MSBuild 表达式中的属性、项和元数据提供了快速信息。快速信息弹出窗口更丰富,有指向相关文档的深层链接,以及指向其他文件引用的超链接,这些超链接可以帮助您了解底层如何使用该属性或项。

如果您想了解如何使用属性或项,可以使用 Ctrl-Click 或 Go to Definition 命令转到定义它的位置。你也可以使用 Find References 命令在所有导入的文件中执行精确的搜索:

不离开编辑器编写代码

即使作为一名经验丰富的 MSBuild 作者,我也经常打开文档来查找 MSBuild 属性、项和元数据的确切名称和允许值。当我使用 MSBuild 编辑器时,我很少这样做,因为它几乎在文件的任何地方都提供智能感知,并根据它的 schema 提供文档:

它对 NuGet 包有特殊的支持,允许你搜索包的 ID,并查看包的描述和链接到它的 NuGet.org 页面:

其他类型也有特殊处理,例如语言文化:

在 MSBuild 表达式中也支持智能感知,包括属性函数和项函数:

编辑器并不局限于在其 schema 中定义的那些属性和项。它扫描所有导入的 MSBuild 文件,并为在这些文件中找到的任何属性、项、元数据和目标提供“推断完成”。更棒的是,工具提示有一个超链接,指向属性或项的应用场景:

及早发现问题

MSBuild 编辑器的验证不仅仅是 XML 验证。它将类型系统覆盖到 MSBuild 上,因此您将获得关于 URL 或版本字符串等的格式错误。它对 MSBuild 表达式格式的理解意味着您无需运行构建就可以捕获格式不正确的条件和表达式。

甚至还有一些 Roslyn 风格的分析器和代码修复。

增强 MSBuild 编辑体验

MSBuild 编辑器由一种新的 MSBuild 特定的基于 json 的 schema 格式提供支持,该格式允许为 MSBuild 属性、项、项元数据和 targets 定义文档和类型注释。它包括 .NET SDK 和其他常用 targets 和 SDK 的内置schema。

但是,您也可以为自己的 MSBuild targets 编写 schema,以允许 MSBuild 编辑器在编辑或使用它们时提供更丰富的体验。如果您是包含 build targets 的 NuGet 包的作者,那么您可以在 NuGet 包中发布该 sidecar schema,以便为包的使用者提供更好的 MSBuild 编辑体验。

Q&A

Q:扩展有一个 GitHub 仓库-我可以从源代码构建和贡献吗?

A:绝对!只需克隆仓库及其子模块,在 Visual Studio 中打开,然后按 F5。

Q:为什么扩展仓库、命名空间和程序集的名字中有“MonoDevelop”?

A:MSBuild 编辑器是我最初在2015年3月为 MonoDevelop IDE 创建的扩展的后代。尽管它在过去几年里发展了很多,包括移植到 Visual Studio,但出于怀旧的考虑,我保留了内部名称。

Q:我可以在 Visual Studio Code 中使用扩展吗?

A:还不行!我目前正在移植扩展到 LSP(语言服务器协议,Language Server Protocol),所以它可以在 Visual Studio Code 扩展中使用。虽然 LSP 是新扩展的明显选择,但这个代码库可以追溯到 Visual Studio Code 发布之前。

我们渴望您的反馈!

如果您想尝试下,你可以通过在 Visual Studio 扩展管理中搜索“MSBuild Editor”找到它,或者从 Visual Studio Marketplace 下载它。该扩展目前仅适用于 Visual Studio,但将其移植到 Visual Studio Code 的工作正在进行中。

如果您遇到任何此扩展的任何问题,请发布其到 GitHub 问题页面。扩展是开源的,欢迎贡献。请填写这份调查问卷,让我们了解您的经历。我们感谢您的反馈,它将有助于指导实验如何发展,以及 MSBuild 编辑器是否会成为 .NET 开发体验的官方支持部分。

原文链接:https://devblogs.microsoft.com/visualstudio/experimental-msbuild-editor/