当前位置: 首页 > news >正文

PostgreSQL源码分析 —— FunctionScan

本文分析一下FunctionScan的源码,加深一下理解。以SELECT * FROM generate_series(2,4);为例进行分析。

postgres@postgres=# SELECT * FROM generate_series(2,4);generate_series 
-----------------234
(3 rows)postgres@postgres=# explain SELECT * FROM generate_series(2,4);QUERY PLAN                             
--------------------------------------------------------------------Function Scan on generate_series  (cost=0.00..0.03 rows=3 width=4)
(1 row)
查询优化器

解析层面流程如下:

exec_simple_query
--> pg_parse_query--> raw_parser--> base_yyparse
--> pg_analyze_and_rewrite

语法表示可查看gram.y中的定义。

simple_select:SELECT opt_all_clause opt_target_listinto_clause from_clause where_clausegroup_clause having_clause window_clause{SelectStmt *n = makeNode(SelectStmt);n->targetList = $3;n->intoClause = $4;n->fromClause = $5;n->whereClause = $6;n->groupClause = ($7)->list;n->havingClause = $8;n->windowClause = $9;$$ = (Node *)n;}
from_clause:FROM from_list							{ $$ = $2; }| /*EMPTY*/								{ $$ = NIL; };from_list:table_ref								{ $$ = list_make1($1); }| from_list ',' table_ref				{ $$ = lappend($1, $3); };table_ref:	relation_expr opt_alias_clause{$1->alias = $2;$$ = (Node *) $1;}| func_table func_alias_clause{RangeFunction *n = (RangeFunction *) $1;n->alias = linitial($2);n->coldeflist = lsecond($2);$$ = (Node *) n;}
/** func_table represents a function invocation in a FROM list. It can be* a plain function call, like "foo(...)", or a ROWS FROM expression with* one or more function calls, "ROWS FROM (foo(...), bar(...))",* optionally with WITH ORDINALITY attached.* In the ROWS FROM syntax, a column definition list can be given for each* function, for example:*     ROWS FROM (foo() AS (foo_res_a text, foo_res_b text),*                bar() AS (bar_res_a text, bar_res_b text))* It's also possible to attach a column definition list to the RangeFunction* as a whole, but that's handled by the table_ref production.*/
func_table: func_expr_windowless opt_ordinality{RangeFunction *n = makeNode(RangeFunction);n->lateral = false;n->ordinality = $2;n->is_rowsfrom = false;n->functions = list_make1(list_make2($1, NIL));/* alias and coldeflist are set by table_ref production */$$ = (Node *) n;}| ROWS FROM '(' rowsfrom_list ')' opt_ordinality{RangeFunction *n = makeNode(RangeFunction);n->lateral = false;n->ordinality = $6;n->is_rowsfrom = true;n->functions = $4;/* alias and coldeflist are set by table_ref production */$$ = (Node *) n;};func_expr_windowless:func_application						{ $$ = $1; }| func_expr_common_subexpr				{ $$ = $1; };func_application: func_name '(' ')'{$$ = (Node *) makeFuncCall($1, NIL, @1);}| func_name '(' func_arg_list opt_sort_clause ')'{FuncCall *n = makeFuncCall($1, $3, @1);n->agg_order = $4;$$ = (Node *)n;}

关键数据结构:

// select语句的抽象语法树表示
typedef struct SelectStmt
{NodeTag		type;// 对应select *List	   *targetList;		/* the target list (of ResTarget) */  // *// 对应         from generate_series(2,4)List	   *fromClause;		/* the FROM clause */  // 保存RangeFunction节点// ...... } SelectStmt;// 范围表:函数类型范围表
/** RangeFunction - function call appearing in a FROM clause*/
typedef struct RangeFunction
{NodeTag		type;bool		lateral;		/* does it have LATERAL prefix? */bool		ordinality;		/* does it have WITH ORDINALITY suffix? */bool		is_rowsfrom;	/* is result of ROWS FROM() syntax? */List	   *functions;		/* per-function information, see above */Alias	   *alias;			/* table alias & optional column aliases */List	   *coldeflist;		/* list of ColumnDef nodes to describe result of function returning RECORD */
} RangeFunction;// 函数调用 ,函数名,参数列表
typedef struct FuncCall
{NodeTag		type;List	   *funcname;		/* qualified name of function */List	   *args;			/* the arguments (list of exprs) */List	   *agg_order;		/* ORDER BY (list of SortBy) */Node	   *agg_filter;		/* FILTER clause, if any */bool		agg_within_group;	/* ORDER BY appeared in WITHIN GROUP */bool		agg_star;		/* argument was really '*' */bool		agg_distinct;	/* arguments were labeled DISTINCT */bool		func_variadic;	/* last argument was labeled VARIADIC */struct WindowDef *over;		/* OVER clause, if any */int			location;		/* token location, or -1 if unknown */
} FuncCall;

语义分析流程:

pg_analyze_and_rewrite
--> pg_analyze--> transformStmt--> transformSelectStmt--> transformFromClause  // 处理Function范围表--> transformFromClauseItem--> transformRangeFunction--> transformExpr--> transformFuncCall--> ParseFuncOrColumn // 构造FuncExpr--> addRangeTableEntryForFunction--> get_expr_result_type--> internal_get_result_type--> build_function_result_tupdesc_t--> get_type_func_class--> buildRelationAliases--> buildNSItemFromTupleDesc--> transformTargetList
--> pg_rewrite_query

关键数据结构:

/* FuncExpr - expression node for a function call*/
typedef struct FuncExpr
{Expr		xpr;Oid			funcid;			/* PG_PROC OID of the function */Oid			funcresulttype; /* PG_TYPE OID of result value */bool		funcretset;		/* true if function returns set */bool		funcvariadic;	/* true if variadic arguments have been* combined into an array last argument */CoercionForm funcformat;	/* how to display this function call */Oid			funccollid;		/* OID of collation of result */Oid			inputcollid;	/* OID of collation that function should use */List	   *args;			/* arguments to the function */int			location;		/* token location, or -1 if unknown */
} FuncExpr;/** RangeTblFunction -*	  RangeTblEntry subsidiary data for one function in a FUNCTION RTE.*/
typedef struct RangeTblFunction
{NodeTag		type;Node	   *funcexpr;		/* expression tree for func call */int			funccolcount;	/* number of columns it contributes to RTE *//* These fields record the contents of a column definition list, if any: */List	   *funccolnames;	/* column names (list of String) */List	   *funccoltypes;	/* OID list of column type OIDs */List	   *funccoltypmods; /* integer list of column typmods */List	   *funccolcollations;	/* OID list of column collation OIDs *//* This is set during planning for use by the executor: */Bitmapset  *funcparams;		/* PARAM_EXEC Param IDs affecting this func */
} RangeTblFunction;

最终生成查询树Query,下一步是生成执行计划。

优化器主流程:

pg_plan_queries
--> pg_plan_query--> planner--> standard_planner   调用标准优化器
standard_planner
--> subquery_planner--> preprocess_function_rtes--> pull_up_subqueries  // 上拉子查询--> grouping_planner--> query_planner--> setup_simple_rel_arrays--> add_base_rels_to_query  // 构造RelOptInfo--> build_simple_rel--> make_one_rel--> set_base_rel_sizes--> set_rel_size--> set_function_size_estimates--> set_baserel_size_estimates--> set_base_rel_pathlists--> set_rel_pathlist--> set_function_pathlist--> create_functionscan_path  // 生成FunctionScanPath--> make_rel_from_joinlist--> apply_scanjoin_target_to_paths
--> create_plan--> create_scan_plan--> create_functionscan_plan--> make_functionscan

核心函数:

FunctionScan *create_functionscan_plan(PlannerInfo *root, Path *best_path, List *tlist, List *scan_clauses)
{FunctionScan *scan_plan;Index		scan_relid = best_path->parent->relid;RangeTblEntry *rte;List	   *functions;rte = planner_rt_fetch(scan_relid, root);functions = rte->functions;   // 函数表达式 /* Sort clauses into best execution order */scan_clauses = order_qual_clauses(root, scan_clauses);/* Reduce RestrictInfo list to bare expressions; ignore pseudoconstants */scan_clauses = extract_actual_clauses(scan_clauses, false);/* Replace any outer-relation variables with nestloop params */if (best_path->param_info){scan_clauses = (List *)replace_nestloop_params(root, (Node *) scan_clauses);/* The function expressions could contain nestloop params, too */functions = (List *) replace_nestloop_params(root, (Node *) functions);}scan_plan = make_functionscan(tlist, scan_clauses, scan_relid, functions, rte->funcordinality);copy_generic_path_info(&scan_plan->scan.plan, best_path);return scan_plan;
}
执行器

生成执行计划后,进入执行器。
主流程如下:

PortalStart
--> ExecutorStart--> InitPlan--> ExecInitFunctionScan--> ExecInitTableFunctionResult--> get_expr_result_type--> ExecInitScanTupleSlot--> ExecInitResultTypeTL--> ExecTypeFromTL--> ExecAssignScanProjectionInfo
PortalRun
--> ExecutorRun--> ExecutePlan--> ExecFunctionScan--> ExecScan--> ExecScanFetch--> FunctionNext   // 首先获取函数的结果集保存起来--> ExecMakeTableFunctionResult--> FunctionCallInvoke--> generate_series_int4--> generate_series_step_int4--> tuplestore_gettupleslot  // 第一次执行获得结果集后,每次从tuplestore中取出
PortalDrop

核心代码:

/* ----------------------------------------------------------------*		ExecFunctionScan(node)**		Scans the function sequentially and returns the next qualifying*		tuple.*		We call the ExecScan() routine and pass it the appropriate*		access method functions.* ----------------------------------------------------------------*/
TupleTableSlot *ExecFunctionScan(PlanState *pstate)
{FunctionScanState *node = castNode(FunctionScanState, pstate);return ExecScan(&node->ss,(ExecScanAccessMtd) FunctionNext,(ExecScanRecheckMtd) FunctionRecheck);
}TupleTableSlot *
ExecScan(ScanState *node,ExecScanAccessMtd accessMtd,	/* function returning a tuple */ExecScanRecheckMtd recheckMtd)
{ExprContext *econtext;ExprState  *qual;ProjectionInfo *projInfo;/* Fetch data from node */qual = node->ps.qual;projInfo = node->ps.ps_ProjInfo;econtext = node->ps.ps_ExprContext;/* interrupt checks are in ExecScanFetch *//* If we have neither a qual to check nor a projection to do, just skip* all the overhead and return the raw scan tuple.*/if (!qual && !projInfo){ResetExprContext(econtext);return ExecScanFetch(node, accessMtd, recheckMtd);}/* Reset per-tuple memory context to free any expression evaluation* storage allocated in the previous tuple cycle.*/ResetExprContext(econtext);/* get a tuple from the access method.  Loop until we obtain a tuple that* passes the qualification.*/for (;;){TupleTableSlot *slot;slot = ExecScanFetch(node, accessMtd, recheckMtd);// ......}
}/** ExecScanFetch -- check interrupts & fetch next potential tuple** This routine is concerned with substituting a test tuple if we are* inside an EvalPlanQual recheck.  If we aren't, just execute* the access method's next-tuple routine. */
TupleTableSlot *
ExecScanFetch(ScanState *node,ExecScanAccessMtd accessMtd,ExecScanRecheckMtd recheckMtd)
{EState	   *estate = node->ps.state;CHECK_FOR_INTERRUPTS();if (estate->es_epq_active != NULL){// ......}/* Run the node-type-specific access method function to get the next tuple */return (*accessMtd) (node);
}/* ----------------------------------------------------------------*		FunctionNext**		This is a workhorse for ExecFunctionScan* ---------------------------------------------------------------- */
TupleTableSlot *FunctionNext(FunctionScanState *node)
{EState	   *estate;ScanDirection direction;TupleTableSlot *scanslot;bool		alldone;int64		oldpos;int			funcno;int			att;/* get information from the estate and scan state */estate = node->ss.ps.state;direction = estate->es_direction;scanslot = node->ss.ss_ScanTupleSlot;if (node->simple){/* Fast path for the trivial case: the function return type and scan* result type are the same, so we fetch the function result straight* into the scan result slot. No need to update ordinality or rowcounts either. */Tuplestorestate *tstore = node->funcstates[0].tstore;/** If first time through, read all tuples from function and put them* in a tuplestore. Subsequent calls just fetch tuples from* tuplestore.*/if (tstore == NULL){node->funcstates[0].tstore = tstore =ExecMakeTableFunctionResult(node->funcstates[0].setexpr,node->ss.ps.ps_ExprContext,node->argcontext,node->funcstates[0].tupdesc,node->eflags & EXEC_FLAG_BACKWARD);/** paranoia - cope if the function, which may have constructed the* tuplestore itself, didn't leave it pointing at the start. This* call is fast, so the overhead shouldn't be an issue.*/tuplestore_rescan(tstore);}/* Get the next tuple from tuplestore. */(void) tuplestore_gettupleslot(tstore,ScanDirectionIsForward(direction),false,scanslot);return scanslot;}/** Increment or decrement ordinal counter before checking for end-of-data,* so that we can move off either end of the result by 1 (and no more than* 1) without losing correct count.  See PortalRunSelect for why we can* assume that we won't be called repeatedly in the end-of-data state.*/oldpos = node->ordinal;if (ScanDirectionIsForward(direction))node->ordinal++;elsenode->ordinal--;/** Main loop over functions.** We fetch the function results into func_slots (which match the function* return types), and then copy the values to scanslot (which matches the* scan result type), setting the ordinal column (if any) as well.*/ExecClearTuple(scanslot);att = 0;alldone = true;for (funcno = 0; funcno < node->nfuncs; funcno++){FunctionScanPerFuncState *fs = &node->funcstates[funcno];int			i;/** If first time through, read all tuples from function and put them* in a tuplestore. Subsequent calls just fetch tuples from* tuplestore.*/if (fs->tstore == NULL){fs->tstore =ExecMakeTableFunctionResult(fs->setexpr,node->ss.ps.ps_ExprContext,node->argcontext,fs->tupdesc,node->eflags & EXEC_FLAG_BACKWARD);/** paranoia - cope if the function, which may have constructed the* tuplestore itself, didn't leave it pointing at the start. This* call is fast, so the overhead shouldn't be an issue.*/tuplestore_rescan(fs->tstore);}/** Get the next tuple from tuplestore.** If we have a rowcount for the function, and we know the previous* read position was out of bounds, don't try the read. This allows* backward scan to work when there are mixed row counts present.*/if (fs->rowcount != -1 && fs->rowcount < oldpos)ExecClearTuple(fs->func_slot);else(void) tuplestore_gettupleslot(fs->tstore,ScanDirectionIsForward(direction),false,fs->func_slot);if (TupIsNull(fs->func_slot)){/** If we ran out of data for this function in the forward* direction then we now know how many rows it returned. We need* to know this in order to handle backwards scans. The row count* we store is actually 1+ the actual number, because we have to* position the tuplestore 1 off its end sometimes.*/if (ScanDirectionIsForward(direction) && fs->rowcount == -1)fs->rowcount = node->ordinal;/** populate the result cols with nulls*/for (i = 0; i < fs->colcount; i++){scanslot->tts_values[att] = (Datum) 0;scanslot->tts_isnull[att] = true;att++;}}else{/** we have a result, so just copy it to the result cols.*/slot_getallattrs(fs->func_slot);for (i = 0; i < fs->colcount; i++){scanslot->tts_values[att] = fs->func_slot->tts_values[i];scanslot->tts_isnull[att] = fs->func_slot->tts_isnull[i];att++;}/** We're not done until every function result is exhausted; we pad* the shorter results with nulls until then.*/alldone = false;}}/** ordinal col is always last, per spec.*/if (node->ordinality){scanslot->tts_values[att] = Int64GetDatumFast(node->ordinal);scanslot->tts_isnull[att] = false;}/** If alldone, we just return the previously-cleared scanslot.  Otherwise,* finish creating the virtual tuple.*/if (!alldone)ExecStoreVirtualTuple(scanslot);return scanslot;
}

相关文章:

PostgreSQL源码分析 —— FunctionScan

本文分析一下FunctionScan的源码&#xff0c;加深一下理解。以SELECT * FROM generate_series(2,4);为例进行分析。 postgrespostgres# SELECT * FROM generate_series(2,4);generate_series -----------------234 (3 rows)postgrespostgres# explain SELECT * FROM generate…...

数据结构-十大排序算法集合(四万字精讲集合)

前言 1&#xff0c;数据结构排序篇章是一个大的工程&#xff0c;这里是一个总结篇章&#xff0c;配备动图和过程详解&#xff0c;从难到易逐步解析。 2&#xff0c;这里我们详细分析几个具备教学意义和实际使用意义的排序&#xff1a; 冒泡排序&#xff0c;选择排序&#xff0c…...

SpringBoot三层架构

目录 一、传统方式 二、三层架构 三、代码拆分 1、dao层 2、service层 3、control层 四、运行结果 一、传统方式 上述代码存在一定的弊端&#xff0c;在进行软件设计和软件开发中提倡单一责任原则&#xff0c;使代码的可读性更强&#xff0c;复杂性更低&#xff0c;可扩展性…...

uniapp微信小程序局部刷新,无感刷新,修改哪条数据刷新哪条

uniapp做微信小程序时&#xff0c;一个商品列表滑到几百条数据时&#xff0c;点进去详情跳转去编辑信息上下架等&#xff0c;修改完成回来商品列表就到第一条数据了&#xff0c;这样页面效果体验感不是很好&#xff0c;是因为我们把数据接口放在onshow中了&#xff0c;每次回来…...

golan的雪花id

今天记录一下 golang的雪花id golang的雪花id 还是比较简单的&#xff0c;其包含的含义以及组成我这就不讲了&#xff0c;好多大佬都有文章写过&#xff0c;我直接上怎么用 先 引入包 go get "github.com/bwmarrin/snowflake" 代码块 func main() {// 设置一个时…...

RK3568 CAN波特率500K接收数据导致CPU4满载

最近调试RK3568 CAN时发现&#xff0c;当CAN作为接收端&#xff0c;在快速接收数据时会导致cpu4满载。down掉can口或者断开外设时恢复正常。并且问题只是在部门CPU版本上出现。在CAN接收中断中打印log&#xff0c;能发现log是按照接收数据的时间打印的。 驱动(rockchip_canfd…...

AI实战 | 使用元器打造浪漫仪式小管家

浪漫仪式小管家 以前我们曾经打造过学习助手和待办助手,但这一次,我们决定创造一个与众不同的智能体,而浪漫将成为我们的主题。我们选择浪漫作为主题,是因为我们感到在之前的打造过程中缺乏了一些仪式感,无法给对方带来真正的惊喜。因此,这一次我们计划慢慢调试,将它发…...

什么是隐马尔可夫模型?

文章目录 一、说明二、玩具HMM&#xff1a;5′拼接位点识别三、那么&#xff0c;隐藏了什么&#xff1f;四、查找最佳状态路径五、超越最佳得分对齐六、制作更逼真的模型七、收获 关键词&#xff1a;hidden markov model 一、说明 被称为隐马尔可夫模型的统计模型是计算生物学…...

qt中使用qsqlite连接数据库,却没有在本地文件夹中生成db文件

exe运行起来之后&#xff0c;发现没有在exe文件夹下生成数据库文件&#xff0c;&#xff0c;之前可以&#xff0c;但中间莫名其妙不行了&#xff0c;代码如下 // 建立和SQlite数据库的连接database QSqlDatabase::addDatabase("QSQLITE");// 设置数据库文件的名字da…...

Django的‘通用视图TemplateView’

使用通用视图的好处是&#xff1a;如果有一个html需要展示&#xff0c;不需要写view视图函数&#xff0c;直接写好url即可。 使用通用视图的步骤如下&#xff1a; 1、编辑项目urls.py文件 from django.views.generic import TemplateView 在该文件的映射表中添加&#xff1a…...

java功能实现在某个时间范围之内输出true,不在某个范围输出false,时间精确到分钟

import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class DateTimeChecker { private static final Logger log LoggerFactory.getLogger(DateTimeChecker.class); /** * 检查当前时间是否在指定的小时和分钟范围内。 * * param startHour 开…...

macbook屏幕录制技巧,这2个方法请你收好

在当今数字化时代&#xff0c;屏幕录制成为了一项不可或缺的技能&#xff0c;无论是教学演示、游戏直播&#xff0c;还是软件操作教程&#xff0c;屏幕录制都能帮助我们更直观地传达信息。MacBook作为苹果公司的标志性产品&#xff0c;其屏幕录制功能也备受用户关注。本文将详细…...

vue-loader

Vue Loader 是一个 webpack 的 loader&#xff0c;它允许你以一种名为单文件组件 (SFCs)的格式撰写 Vue 组件 起步 安装 npm install vue --save npm install webpack webpack-cli style-loader css-loader html-webpack-plugin vue-loader vue-template-compiler webpack…...

IO系列(十) -TCP 滑动窗口原理介绍(上)

一、摘要 之前在上分享网络编程知识文章的时候&#xff0c;有网友写下一条留言&#xff1a;“可以写写一篇关于 TCP 滑动窗口原理的文章吗&#xff1f;”。 当时没有立即回复&#xff0c;经过查询多方资料&#xff0c;发现这个 TCP 真的非常非常的复杂&#xff0c;就像一个清…...

IPython 使用技巧整理

IPython 是一个增强的 Python 交互式 shell&#xff0c;提供了许多实用的功能和特性&#xff0c;使得 Python 编程和数据科学工作变得更加便捷和高效。以下是一些 IPython 的使用技巧整理&#xff1a; 1. 自动补全和查询 Tab 补全&#xff1a;在 IPython 中&#xff0c;你可以…...

Python 引入中文py文件

目录 背景 思路 importlib介绍 使用方法 1.导入内置库 importlib.util 2.创建模块规格对象 spec importlib.util.spec_from_file_location("example_module", "example.py") 3.创建模块对象 module importlib.util.module_from_spec(spec) …...

qt 实现模拟实际物体带速度的移动(水平、垂直、斜角度)——————附带完整代码

文章目录 0 效果1 原理1.1 图片旋转1.2 物体按照现实中的实际距离带真实速度移动 2 完整实现2.1 将车辆按钮封装为一个类&#xff1a;2.2 调用方法 3 完整代码参考 0 效果 实现后的效果如下 可以显示属性&#xff08;继承自QToolButton&#xff09;: 鼠标悬浮显示文字 按钮…...

驱动开发(三):内核层控制硬件层

驱动开发系列文章&#xff1a; 驱动开发&#xff08;一&#xff09;&#xff1a;驱动代码的基本框架 驱动开发&#xff08;二&#xff09;&#xff1a;创建字符设备驱动 驱动开发&#xff08;三&#xff09;&#xff1a;内核层控制硬件层​​​​​​​ ←本文 目录…...

企业邮箱大附件无法上传?无法确认接收状态?这样解决就行

Outlook邮箱作为最常用的邮箱系统&#xff0c;被全世界企业采用作为内部通用沟通方式&#xff0c;但Outlook邮箱却有着明显的使用缺陷&#xff0c;如邮箱大附件上传障碍及附件接收无提示等。 1、企业邮箱大附件无法上传 Outlook企业邮箱大附件的上传上限一般是50M&#xff0c;…...

Kotlin 数据类(Data Class)

Kotlin 数据类&#xff08;Data Class&#xff09;是一种特别用于持有数据的类。它们简化了数据类的创建&#xff0c;并提供了一些自动生成的方法。下面详细介绍 Kotlin 数据类的原理和使用方法。 数据类的定义 Kotlin 中的数据类使用 data 关键字定义。例如&#xff1a; da…...

手游刚开服就被攻击怎么办?如何防御DDoS?

开服初期是手游最脆弱的阶段&#xff0c;极易成为DDoS攻击的目标。一旦遭遇攻击&#xff0c;可能导致服务器瘫痪、玩家流失&#xff0c;甚至造成巨大经济损失。本文为开发者提供一套简洁有效的应急与防御方案&#xff0c;帮助快速应对并构建长期防护体系。 一、遭遇攻击的紧急应…...

拉力测试cuda pytorch 把 4070显卡拉满

import torch import timedef stress_test_gpu(matrix_size16384, duration300):"""对GPU进行压力测试&#xff0c;通过持续的矩阵乘法来最大化GPU利用率参数:matrix_size: 矩阵维度大小&#xff0c;增大可提高计算复杂度duration: 测试持续时间&#xff08;秒&…...

关于 WASM:1. WASM 基础原理

一、WASM 简介 1.1 WebAssembly 是什么&#xff1f; WebAssembly&#xff08;WASM&#xff09; 是一种能在现代浏览器中高效运行的二进制指令格式&#xff0c;它不是传统的编程语言&#xff0c;而是一种 低级字节码格式&#xff0c;可由高级语言&#xff08;如 C、C、Rust&am…...

Unit 1 深度强化学习简介

Deep RL Course ——Unit 1 Introduction 从理论和实践层面深入学习深度强化学习。学会使用知名的深度强化学习库&#xff0c;例如 Stable Baselines3、RL Baselines3 Zoo、Sample Factory 和 CleanRL。在独特的环境中训练智能体&#xff0c;比如 SnowballFight、Huggy the Do…...

uniapp中使用aixos 报错

问题&#xff1a; 在uniapp中使用aixos&#xff0c;运行后报如下错误&#xff1a; AxiosError: There is no suitable adapter to dispatch the request since : - adapter xhr is not supported by the environment - adapter http is not available in the build 解决方案&…...

MySQL用户和授权

开放MySQL白名单 可以通过iptables-save命令确认对应客户端ip是否可以访问MySQL服务&#xff1a; test: # iptables-save | grep 3306 -A mp_srv_whitelist -s 172.16.14.102/32 -p tcp -m tcp --dport 3306 -j ACCEPT -A mp_srv_whitelist -s 172.16.4.16/32 -p tcp -m tcp -…...

Springboot社区养老保险系统小程序

一、前言 随着我国经济迅速发展&#xff0c;人们对手机的需求越来越大&#xff0c;各种手机软件也都在被广泛应用&#xff0c;但是对于手机进行数据信息管理&#xff0c;对于手机的各种软件也是备受用户的喜爱&#xff0c;社区养老保险系统小程序被用户普遍使用&#xff0c;为方…...

日常一水C

多态 言简意赅&#xff1a;就是一个对象面对同一事件时做出的不同反应 而之前的继承中说过&#xff0c;当子类和父类的函数名相同时&#xff0c;会隐藏父类的同名函数转而调用子类的同名函数&#xff0c;如果要调用父类的同名函数&#xff0c;那么就需要对父类进行引用&#…...

stm32wle5 lpuart DMA数据不接收

配置波特率9600时&#xff0c;需要使用外部低速晶振...

二维FDTD算法仿真

二维FDTD算法仿真&#xff0c;并带完全匹配层&#xff0c;输入波形为高斯波、平面波 FDTD_二维/FDTD.zip , 6075 FDTD_二维/FDTD_31.m , 1029 FDTD_二维/FDTD_32.m , 2806 FDTD_二维/FDTD_33.m , 3782 FDTD_二维/FDTD_34.m , 4182 FDTD_二维/FDTD_35.m , 4793...