主頁 >  其他 > 如何將Python演算法模型注冊成Spark UDF函式實作全景模型部署

如何將Python演算法模型注冊成Spark UDF函式實作全景模型部署

2021-11-03 07:59:20 其他

本文作者來自MLSQL社區 & Kyligence 機器學習平臺工程師 Andie Huang

背景 Background

對于演算法業務團隊來說,將訓練好的模型部署成服務的業務場景是非常常見的,通常會應用于三個場景:

  1. 部署到流式程式里,比如風控需要通過流式處理來實時監控,
  2. 部署到批任務中
  3. 部署成API服務

然而在現實世界中,很多演算法工程師都會遇到需要花費很多精力在模型部署工程上的問題,

  1. 平臺割裂,訓練和部署是在不同平臺完成的,
  2. 配合問題,部署一個模型,需要研發工程師,運維配合,才能完成這件事,
  3. 技術問題,一般地,大資料里的批流亦或是Web服務一般用Java/Scala/C++偏多些,而AI演算法模型一般都是通過Python來生成的,存在語言障礙,

傳統上,想要把演算法部署成服務,會用到如下方法:

  • 比如基于 Tornado 框架把一個 python 模型部署成 RestfulAPI 的服務,或者如果是 Tensorflow 訓練的模型可以用 Tensorflow Serving 的方式結合 Docker 去部署成 RPC/ Restful API 服務,這些能夠幫助用戶實作模型部署的意圖,只是不同的方式都會存在優缺點以及問題;

  • 比如用 Python/C++ 開發的模型,要做成 RestfulAPI 或者想做成流批處理可能得跨語言平臺,一般想到用 Spark,這個時候就需要動用 JNI,而跨語言行程之間又面臨資料傳輸的效率問題等;

傳統的這些方法,無法統一完成批,流,web服務的部署,無法解決平臺割裂,無法解決協作問題,

與傳統方式不同,MLSQL 通過融合Ray框架,通過UDF 打通了大資料和Python的生態隔離,完成了訓練和模型部署的統一,同時也完美解決了Python模型部署的三個問題,

Ray 是 UC Berkeley RISELab 新推出的高性能的面對 AI 的分布式執行框架[1,2],它使用了和傳統分布式計算系統不一樣的架構和對分布式計算的抽象方式,具有比 Spark 更優異的計算性能,

下面詳細介紹幾種比較流行的傳統模型部署方式的流程,用戶所面臨的痛點,以及 MLSQL 的部署方案與之對比的優點

傳統模型部署方法

基于 Tornado 的模型部署

傳統的 Tornado 方式的模型部署,鏈路較長,首先用戶需要在訓練節點里,訓練好模型,并且寫好預測代碼,然后將模型以及預測代碼持久化成 pickle 檔案,由于訓練節點和預測節點是分離的,所以需要中間的存盤系統作為媒介,以便服務端 server 拉取模型和預測代碼,服務端拉取模型后需要將模型反序列化,用 tornado 拉起模型服務,

請添加圖片描述

【總結】這種方式在流程上是簡單易懂,但是也存在很多問題,給部署工程師帶來很大的困擾,首先部署工程師除了要負責部署模型,還需要考慮負載均衡,節點監控,維護成本,資源浪費等額外的問題上,同時,基于 Tornado 部署成的 restful api 服務,性能在 QPS 比較大的場景里(e.g., 搜索,推薦,廣告等)難以達到要求,
MLSQL 注冊 UDF 的解決方案較 Tornado 而言,較為輕便,其巧妙地利用了Ray對資源的控制,為開發者省下集群管理,資源分配和調度甚至是負載均衡等額外作業,開發者只需要根據不同任務的需求,設定cpu即可,

基于 Tensorflow Serving 的模型部署

為了服務開發者將訓練好的 Tensorflow 模型部署線上生產環境,Google 提供了 TensorFlow Serving,可以將訓練好的模型直接上線并提供服務,大概作業流程如下:模型檔案存盤在存盤系統中,source 模塊會創建一個 Loader,加載模型資訊,Source 會通知 DynamicManager 模塊有新的模型需要加載,Manger 模塊會根據 VersionPolicy 的演算法制定模型更新策略,來確定 Loader 加載是否加載最新的模型,當客戶端請求模型時候,可以指定模型版本,也可以用最新的模型,

請添加圖片描述

【總結】Tensorflow 的 Serving 模塊對比 Tornado 部署模型服務而言,輕便了許多,同時其模型版本管理模塊很大程度解決了模型版本管理和自更新的問題,相比上一種方式,部署工程師節省了開發模型自更新演算法和模型管理模塊的時間,但是 Google Tensorflow Serving 的許多用戶仍然存在使用上的痛點,比如,最直觀的,資料處理和特征工程部分仍然無法直接部署服務端,需要在客戶端進行處理,此外,若想引入流批處理生資料,還需要接入流批處理(例如 Spark or Flink)等處理框架,

與 Tensorflow Serving 不同的是,MLSQL 選擇 Ray 作為計算框架,天然支持分布式計算,無論是對離線的訓練,還是在線部署都能很好的支持分布式計算,對于在線特征工程部分,也充分利用了 Ray 的分布式計算,以及對 pands 和 numpy 天然支持的優勢,能夠高效地進行在線生資料的分布式處理,再喂給模型得到打分結果,

MLSQL 模型部署 UDF 函式

MLSQL 的執行引擎是基于 Spark 的,如果能夠把一個模型注冊成一個 Spark 的 UDF,然后結合其他函式,我們便能通過函陣列合完成一個端到端的預測流程, MLSQL 已經支持使用 Java/Scala 來寫 UDF,而且可以使用 MLSQL 語法來完成注冊,解決了以前開發 UDF 需要重啟服務的痛點,
比如使用 Scala 寫 UDF 的代碼類似這樣:


register ScriptUDF.`` as arrayLast where 
lang="scala"
and code='''def apply(a:Seq[String])={
      a.last
}'''
and udfType="udf";

select arrayLast(split("a.b.c",".")) as c as output;

將內置演算法訓練好的模型注冊成 UDF 的代碼是這樣的:

register RandomForest.`/tmp/model` as model_predict;
select vec_array(model_predict(features)) from mock_data as output;

與此同時,我們可以看到,MLSQL 模型部署操作暴露給用戶的仍然是類 SQL 的語法,可以非常方便快速地讓工程師上手,降低工程師的作業量提升模型部署效率,

但是我們知道大部分演算法可能都是使用 Python 來開發的,而且比如深度學習模型,模型檔案都可能非常大,也就是我們其實需要一個帶狀態的 UDF,這是有挑戰的,但得益于

  1. MLSQL 已經支持 Python 腳本的執行,引入 Ray 后,Python 腳本的分布式執行也不是問題了,計算性能和可擴展性上都有了保證,
  2. MLSQL 利用 Arrow 做資料傳輸格式,使的資料在跨語言行程傳輸的性能得到保證
  3. MLSQL 內置的增強資料湖支持目錄以表的形式存盤,這樣可以很好的把模型通過表的方式保存在資料湖里,支持版本以及更新覆寫,同時也方便了 Spark / Ray 之間的模型傳輸,

有了前面這些基礎,我們就可以使用和內置演算法一樣的方式將一個 Python 的模型注冊成一個 UDF 函式,這樣可以將模型應用于批,流,以及 Web 服務中,

【總結】MLSQL 基于 Ray 的計算框架進行 AI 模型的部署能夠具備以下幾個特點:
1)實作模型預測的分布式異步呼叫
2)充分利用Ray的內置功能,實作記憶體調度和負載均衡
3)對Pandas/Numpy 的分布式支持
4)對Python代碼的支持
5)預測性能出眾等

具體地,我們將在下個章節展示 MLSQL 基于 Ray 從模型訓練再到模型模型部署的全流程 demo,并展示 MLSQL 部署的背后原理,

如何利用 MLSQL 部署模型訓練

訓練一個 Tensorflow 模型

下面的代碼要在 notebook 模式下運行

首先,準備 minist 資料集


include lib.`github.com/allwefantasy/lib-core` where 
force="true" and
libMirror="gitee.com" and -- proxy configuration.
alias="libCore";

-- dump minist data to object storage
include local.`libCore.dataset.mnist`;
!dumpData /tmp/mnist;


load parquet.`/tmp/mnist` as mnist_data;

在上面的示例中,通過 MLSQL 的模塊支持,引入第三方開發的 lib-core,從而獲得 !dumpData 命令獲取 minist 資料集,

接著就開始拿測驗資料 minist 進行訓練,下面是模型訓練代碼,在訓練代碼中,我們引入 Ray 來訓練:

#%python
#%input=mnist_data
#%schema=file
#%output=mnist_model
#%env=source /Users/allwefantasy/opt/anaconda3/bin/activate ray1.3.0
#%cache=true

import ray
import os
from tensorflow.keras import models,layers
from tensorflow.keras import utils as np_utils
from pyjava.api.mlsql import RayContext
from pyjava.storage import streaming_tar
from pyjava import rayfix
import numpy as np


ray_context = RayContext.connect(globals(),"127.0.0.1:10001")
data_servers = ray_context.data_servers()

def data():
    temp_data = [item for item in RayContext.collect_from(data_servers)]
    train_images = np.array([np.array(item["image"]) for item in temp_data])
    train_labels = np_utils.to_categorical(np.array([item["label"] for item in temp_data])    )
    train_images = train_images.reshape((len(temp_data),28*28))
    return train_images,train_labels

@ray.remote
@rayfix.last
def train():
    train_images,train_labels = data()
    network = models.Sequential()
    network.add(layers.Dense(512,activation="relu",input_shape=(28*28,)))
    network.add(layers.Dense(10,activation="softmax"))
    network.compile(optimizer="rmsprop",loss="categorical_crossentropy",metrics=["accuracy"])
    network.fit(train_images,train_labels,epochs=6,batch_size=128)
    model_path = os.path.join("tmp","minist_model")
    network.save(model_path)
    model_binary = [item for item in streaming_tar.build_rows_from_file(model_path)]
    return model_binary

model_binary = ray.get(train.remote())  
ray_context.build_result(model_binary)

最后把模型保存增強資料湖里:

save overwrite mnist_model as delta.`ai_model.mnist_model`;

模型部署

訓練好模型之后,我們就可以用 MLSQL 的 Register 語法將模型注冊成基于 Ray 的服務了,下面是模型注冊的代碼

把模型注冊成 UDF 函式

!python env "PYTHON_ENV=source /Users/allwefantasy/opt/anaconda3/bin/activate ray1.3.0";
!python conf "schema=st(field(content,string))";
!python conf "mode=model";
!python conf "runIn=driver";
!python conf "rayAddress=127.0.0.1:10001";


-- 加載前面訓練好的tf模型
load delta.`ai_model.mnist_model` as mnist_model;

-- 把模型注冊成udf函式
register Ray.`mnist_model` as model_predict where 
maxConcurrency="8"
and debugMode="true"
and registerCode='''

import ray
import numpy as np
from pyjava.api.mlsql import RayContext
from pyjava.udf import UDFMaster,UDFWorker,UDFBuilder,UDFBuildInFunc

ray_context = RayContext.connect(globals(), context.conf["rayAddress"])

def predict_func(model,v):
    train_images = np.array([v])
    train_images = train_images.reshape((1,28*28))
    predictions = model.predict(train_images)
    return {"value":[[float(np.argmax(item)) for item in predictions]]}

UDFBuilder.build(ray_context,UDFBuildInFunc.init_tf,predict_func)

''' and 
predictCode='''

import ray
from pyjava.api.mlsql import RayContext
from pyjava.udf import UDFMaster,UDFWorker,UDFBuilder,UDFBuildInFunc

ray_context = RayContext.connect(globals(), context.conf["rayAddress"])
UDFBuilder.apply(ray_context)

'''
;

-- 這個代碼可以將磁區數目減少,避免并發太高導致的排隊等待
-- load parquet.`/tmp/mnist` as mnist_data;
-- save mnist_data as parquet.`/tmp/minst-8`  where fileNum="8";

load parquet.`/tmp/minst` as mnist_data;

select cast(image as array<double>) as image from mnist_data limit 100 as new_mnist_data;

select model_predict(array(image)) as predicted  from  new_mnist_data as output;

模型呼叫

模型注冊結束之后,如何呼叫注冊的模型呢?MLSQL 提供最簡易的類 SQL 陳述句做批量(Batch)查詢,具體操作如下展示

load parquet.`/tmp/minst` as mnist_data;

select cast(image as array<double>) as image from mnist_data limit 100 as new_mnist_data;

select model_predict(array(image)) as predicted  from  new_mnist_data as output;

在 MLSQL 里,是由 Pyjava 互通組件去完成 Java Executor 去呼叫 python worker 的,使得可以在 Java 里面去執行 Python 代碼,從而在 SQL 里實作 Python,并且實作資料的互通,
下面,我們針對模型注冊的例子,詳細介紹 MLSQL 里 UDF 注冊是怎么實作的,

PyJava UDF呼叫關系圖

如前面內容所述,對于一個已經訓練好了的模型,注冊成可呼叫的服務,主要需要做以下兩件事:
1)加載已經訓練好的模型
2)拿到需要預測的資料,進行資料處理,喂給模型,得到prediction score【也就是預測函式】,

PyJava 幫用戶做好了第一個流程,第二個流程需要用戶根據自己的使用場景進行自定義,
在 MLSQL 里,模型注冊成 UDF 函式的程序中,用戶主要用以下幾個類,包括 UDFBuilder,UDFMaster,UDF Worker 以及 UDFBuildInFunc,下圖描述了這幾個類之間的關系,

在這里插入圖片描述

總的一句話,pyjava 用 UDFBuilder.build() 這個函式,去幫用戶實作模型的加載以及用戶自定義的預測函式,
UDFBuildInFunc 為用戶提供了模型初始化的通用邏輯,用戶即可以根據自己的業務場景自定義模型初始化函式,也可以呼叫 UDFBuidInFunc 的 init_tf 方法加載模型,
UDFBuilder 是一個靜態工具類,它通過 build 方法創建 Ray 的 actor UDFMaster,并把模型的加載函式以及模型的預測函式參考傳送到 UDFMaster 里,UDFMaster 里主要做 UDFWorker 的初始化,并將從 UDFBuilder 傳過來的模型加載函式和模型預測函式參考傳遞給 UDFWorker,而真正在做預測邏輯的則是 Ray 集群里的 UDFWorker節點,
在拉起的 Ray的節點中,每一個節點對應一個 UDFWorker,每一個 worker 都在呼叫 apply_func,也就是用戶自定義的預測代碼函式,節點里的預測代碼,通過函式參考的方式,從 UDFBuilder 傳遞到 Ray Actors (包括 UDFMaster 以及 UDFWorker),

具體詳細的函式引數介紹,請看 【UDFBuilder 與UDFBuildInFunc引數使用詳解】部分

MLSQL 執行 Python 的互動

我們都知道,MLSQL 本身背后的引擎是基于 Scala 實作的,而 Scala 又是 Java 系的,在大部分的 AI 場景中,模型預測以及預測前的資料處理很多都是基于 Python 實作的,那么在部署模型服務的時候,如何實作 java 行程與 python 行程的資料通訊呢?
下圖闡述了 MLSQL Engine 端實作 Java 行程與 Python 行程之間的通訊方式,在 MLSQL 中,Engine 端(Java Executor)創建 python worker 行程呼叫 pyjava,pyjava 的主要作業就是做 python worker 與 java executor 端的資料通訊(包括資料獲取和資料輸出,并且通過arrow格式 與Java行程進行資料傳輸),具體的互動流程如下圖所示:

在這里插入圖片描述

首先 MLSQL Engine 端會在啟動的 java 應用行程里呼叫 pyjava 模塊,pyjava 中 python SDK 部分的入口是 daemon.py 檔案,該入口檔案的主要功能是創建 python worker,同時擔任資料流的管道角色,worker 的核心邏輯包括,匯入ray, 設定自己的記憶體限制,讀取配置引數,讀取 python 腳本,執行python 腳本(通過 Arrow 傳遞 python 腳本資料),并執行,最后通過 Arrow 傳遞 python 執行結果(也就是本文提到的預測結果)給 MLSQL Engine 端,同時 python worker 執行的輸入資料(也就是本文場景下的模型預測輸入資料)借助 pyarrow 從 MLSQL engine 端獲取,

在 Python Daemon 執行緒中,通過 UDFBuilder 創建構造 Ray Actor 包括 UDFMaster 和 UDFWorker,如上一節所述,UDFMaster 主要充當管理 UDFWorker 節點的功能,真正預測的邏輯在 UDFWoker 的 Ray節點里執行,最后的執行結果通過 Ray 獲取 future 的方式回傳給 PythonContext,python worker再通過 pyarrow 回傳給 MLSQL Engine,

UDFBuilder 與 UDFBuildInFunc 引數使用詳解

UDFBuilder

UDFBuilder.build 這個函式有幾個引數,分別是 ray_context,init_func,apply_func,
ray_context:如上一節所述,PythonContext充當資料互動的作用,RayContext則是基于PythonContext之上的整合,目的是讓Ray集群做真正的資料處理的作業,RayContext可以給worker回傳ray的server地址,方便java executor獲取對應的future資料,

ray_context = RayContext.connect(globals(),"127.0.0.1:10001")

init_func: 模型初始化函式,可以是用戶自定義的模型初始化函式,如果沒有特別定制化的業務場景,可以直接復用 BuilderInFuncinit_tf 函式,UDFBuildInFunc 部分介紹了 init_func 的實作基本思路,

apply_func:模型預測函式,也就是用戶定義的接收到資料之后做的資料處理函式,以及喂給模型整個流程的函式,

def build(ray_context: RayContext,
          init_func: Callable[[List[ClientObjectRef], Dict[str, str]], Any],
          apply_func: Callable[[Any, Any], Any]) -> NoReturn:

UDFBuildInFunc

這里的 init_func 是函式的參考,所以僅需要傳遞一個函式的參考就可以,因為基本大部分的 AI 場景都是 load 模型,然后把模型存盤在某個 storage 里,因此,pyjava 的 UDF 模塊為用戶提供的通用的init_func,也就是 UDFBuildInFunc 里的 init_tf,這里的 init_tf 是 UDFBuildInFunc 的一個靜態函式,可以通過靜態呼叫就可以了,

再來看一下這個 init_tf,用戶需要傳遞的兩個值是,分別是 model_refs,以及 conf,對于 model_refs,它是一個 ray 存盤的 object 型別,也就是說,基于我們上一步在 ray 框架里訓練好的模型,可以通過 ray 的 get 方式獲取得到【因為上一步的 train,是基于 ray.remote 呼叫的,結果會產生】,

class UDFBuildInFunc(object):
    @staticmethod
    def init_tf(model_refs: List[ClientObjectRef], conf: Dict[str, str]) 

[1] https://zhuanlan.zhihu.com/p/111340572 Ray 分布式計算框架介紹

[2] Moritz, Philipp, et al. “Ray: A distributed framework for emerging AI applications.” 13th Symposium on Operating Systems Design and Implementation ({OSDI} 18). 2018.

轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/345694.html

標籤:其他

上一篇:Flink任務問題分析與性能調優

下一篇:asp.net網上化妝品銷售系統VS開發sqlserver資料庫web結構C#編程

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 網閘典型架構簡述

    網閘架構一般分為兩種:三主機的三系統架構網閘和雙主機的2+1架構網閘。 三主機架構分別為內端機、外端機和仲裁機。三機無論從軟體和硬體上均各自獨立。首先從硬體上來看,三機都用各自獨立的主板、記憶體及存盤設備。從軟體上來看,三機有各自獨立的作業系統。這樣能達到完全的三機獨立。對于“2+1”系統,“2”分為 ......

    uj5u.com 2020-09-10 02:00:44 more
  • 如何從xshell上傳檔案到centos linux虛擬機里

    如何從xshell上傳檔案到centos linux虛擬機里及:虛擬機CentOs下執行 yum -y install lrzsz命令,出現錯誤:鏡像無法找到軟體包 前言 一、安裝lrzsz步驟 二、上傳檔案 三、遇到的問題及解決方案 總結 前言 提示:其實很簡單,往虛擬機上安裝一個上傳檔案的工具 ......

    uj5u.com 2020-09-10 02:00:47 more
  • 一、SQLMAP入門

    一、SQLMAP入門 1、判斷是否存在注入 sqlmap.py -u 網址/id=1 id=1不可缺少。當注入點后面的引數大于兩個時。需要加雙引號, sqlmap.py -u "網址/id=1&uid=1" 2、判斷文本中的請求是否存在注入 從文本中加載http請求,SQLMAP可以從一個文本檔案中 ......

    uj5u.com 2020-09-10 02:00:50 more
  • Metasploit 簡單使用教程

    metasploit 簡單使用教程 浩先生, 2020-08-28 16:18:25 分類專欄: kail 網路安全 linux 文章標簽: linux資訊安全 編輯 著作權 metasploit 使用教程 前言 一、Metasploit是什么? 二、準備作業 三、具體步驟 前言 Msfconsole ......

    uj5u.com 2020-09-10 02:00:53 more
  • 游戲逆向之驅動層與用戶層通訊

    驅動層代碼: #pragma once #include <ntifs.h> #define add_code CTL_CODE(FILE_DEVICE_UNKNOWN,0x800,METHOD_BUFFERED,FILE_ANY_ACCESS) /* 更多游戲逆向視頻www.yxfzedu.com ......

    uj5u.com 2020-09-10 02:00:56 more
  • 北斗電力時鐘(北斗授時服務器)讓網路資料更精準

    北斗電力時鐘(北斗授時服務器)讓網路資料更精準 北斗電力時鐘(北斗授時服務器)讓網路資料更精準 京準電子科技官微——ahjzsz 近幾年,資訊技術的得了快速發展,互聯網在逐漸普及,其在人們生活和生產中都得到了廣泛應用,并且取得了不錯的應用效果。計算機網路資訊在電力系統中的應用,一方面使電力系統的運行 ......

    uj5u.com 2020-09-10 02:01:03 more
  • 【CTF】CTFHub 技能樹 彩蛋 writeup

    ?碎碎念 CTFHub:https://www.ctfhub.com/ 筆者入門CTF時時剛開始刷的是bugku的舊平臺,后來才有了CTFHub。 感覺不論是網頁UI設計,還是題目質量,賽事跟蹤,工具軟體都做得很不錯。 而且因為獨到的金幣制度的確讓人有一種想去刷題賺金幣的感覺。 個人還是非常喜歡這個 ......

    uj5u.com 2020-09-10 02:04:05 more
  • 02windows基礎操作

    我學到了一下幾點 Windows系統目錄結構與滲透的作用 常見Windows的服務詳解 Windows埠詳解 常用的Windows注冊表詳解 hacker DOS命令詳解(net user / type /md /rd/ dir /cd /net use copy、批處理 等) 利用dos命令制作 ......

    uj5u.com 2020-09-10 02:04:18 more
  • 03.Linux基礎操作

    我學到了以下幾點 01Linux系統介紹02系統安裝,密碼啊破解03Linux常用命令04LAMP 01LINUX windows: win03 8 12 16 19 配置不繁瑣 Linux:redhat,centos(紅帽社區版),Ubuntu server,suse unix:金融機構,證券,銀 ......

    uj5u.com 2020-09-10 02:04:30 more
  • 05HTML

    01HTML介紹 02頭部標簽講解03基礎標簽講解04表單標簽講解 HTML前段語言 js1.了解代碼2.根據代碼 懂得挖掘漏洞 (POST注入/XSS漏洞上傳)3.黑帽seo 白帽seo 客戶網站被黑帽植入劫持代碼如何處理4.熟悉html表單 <html><head><title>TDK標題,描述 ......

    uj5u.com 2020-09-10 02:04:36 more
最新发布
  • 2023年最新微信小程式抓包教程

    01 開門見山 隔一個月發一篇文章,不過分。 首先回顧一下《微信系結手機號資料庫被脫庫事件》,我也是第一時間得知了這個訊息,然后跟蹤了整件事情的經過。下面是這起事件的相關截圖以及近日流出的一萬條資料樣本: 個人認為這件事也沒什么,還不如關注一下之前45億快遞資料查詢渠道疑似在近日復活的訊息。 訊息是 ......

    uj5u.com 2023-04-20 08:48:24 more
  • web3 產品介紹:metamask 錢包 使用最多的瀏覽器插件錢包

    Metamask錢包是一種基于區塊鏈技術的數字貨幣錢包,它允許用戶在安全、便捷的環境下管理自己的加密資產。Metamask錢包是以太坊生態系統中最流行的錢包之一,它具有易于使用、安全性高和功能強大等優點。 本文將詳細介紹Metamask錢包的功能和使用方法。 一、 Metamask錢包的功能 數字資 ......

    uj5u.com 2023-04-20 08:47:46 more
  • vulnhub_Earth

    前言 靶機地址->>>vulnhub_Earth 攻擊機ip:192.168.20.121 靶機ip:192.168.20.122 參考文章 https://www.cnblogs.com/Jing-X/archive/2022/04/03/16097695.html https://www.cnb ......

    uj5u.com 2023-04-20 07:46:20 more
  • 從4k到42k,軟體測驗工程師的漲薪史,給我看哭了

    清明節一過,盲猜大家已經無心上班,在數著日子準備過五一,但一想到銀行卡里的余額……瞬間心情就不美麗了。最近,2023年高校畢業生就業調查顯示,本科畢業月平均起薪為5825元。調查一出,便有很多同學表示自己又被平均了。看著這一資料,不免讓人想到前不久中國青年報的一項調查:近六成大學生認為畢業10年內會 ......

    uj5u.com 2023-04-20 07:44:00 more
  • 最新版本 Stable Diffusion 開源 AI 繪畫工具之中文自動提詞篇

    🎈 標簽生成器 由于輸入正向提示詞 prompt 和反向提示詞 negative prompt 都是使用英文,所以對學習母語的我們非常不友好 使用網址:https://tinygeeker.github.io/p/ai-prompt-generator 這個網址是為了讓大家在使用 AI 繪畫的時候 ......

    uj5u.com 2023-04-20 07:43:36 more
  • 漫談前端自動化測驗演進之路及測驗工具分析

    隨著前端技術的不斷發展和應用程式的日益復雜,前端自動化測驗也在不斷演進。隨著 Web 應用程式變得越來越復雜,自動化測驗的需求也越來越高。如今,自動化測驗已經成為 Web 應用程式開發程序中不可或缺的一部分,它們可以幫助開發人員更快地發現和修復錯誤,提高應用程式的性能和可靠性。 ......

    uj5u.com 2023-04-20 07:43:16 more
  • CANN開發實踐:4個DVPP記憶體問題的典型案例解讀

    摘要:由于DVPP媒體資料處理功能對存放輸入、輸出資料的記憶體有更高的要求(例如,記憶體首地址128位元組對齊),因此需呼叫專用的記憶體申請介面,那么本期就分享幾個關于DVPP記憶體問題的典型案例,并給出原因分析及解決方法。 本文分享自華為云社區《FAQ_DVPP記憶體問題案例》,作者:昇騰CANN。 DVPP ......

    uj5u.com 2023-04-20 07:43:03 more
  • msf學習

    msf學習 以kali自帶的msf為例 一、msf核心模塊與功能 msf模塊都放在/usr/share/metasploit-framework/modules目錄下 1、auxiliary 輔助模塊,輔助滲透(埠掃描、登錄密碼爆破、漏洞驗證等) 2、encoders 編碼器模塊,主要包含各種編碼 ......

    uj5u.com 2023-04-20 07:42:59 more
  • Halcon軟體安裝與界面簡介

    1. 下載Halcon17版本到到本地 2. 雙擊安裝包后 3. 步驟如下 1.2 Halcon軟體安裝 界面分為四大塊 1. Halcon的五個助手 1) 影像采集助手:與相機連接,設定相機引數,采集影像 2) 標定助手:九點標定或是其它的標定,生成標定檔案及內參外參,可以將像素單位轉換為長度單位 ......

    uj5u.com 2023-04-20 07:42:17 more
  • 在MacOS下使用Unity3D開發游戲

    第一次發博客,先發一下我的游戲開發環境吧。 去年2月份買了一臺MacBookPro2021 M1pro(以下簡稱mbp),這一年來一直在用mbp開發游戲。我大致分享一下我的開發工具以及使用體驗。 1、Unity 官網鏈接: https://unity.cn/releases 我一般使用的Apple ......

    uj5u.com 2023-04-20 07:40:19 more