ORCA优化器浅析——DXLToPlStmt[CTranslatorDXLToPlStmt]

news2024/11/15 9:27:50

在这里插入图片描述
如上图所示是将plan_dxl转为plan_stmt的主入口函数。其主要工作就是创建plan_id_generator、motion_id_generator、param_id_generator和table_list、subplans_list,并将其设置到CContextDXLToPlStmt dxl_to_plan_stmt_ctxt中供后续流程调用;初始化CTranslatorDXLToPlStmt类,形参为MDACCESSOR和CContextDXLToPlStmt;最终调用dxl_to_plan_stmt_translator.GetPlannedStmtFromDXL实现DXL -> PlannedStmt的转化。

//---------------------------------------------------------------------------
//	@function:
//		COptTasks::ConvertToPlanStmtFromDXL
//	@doc:
//		Translate a DXL tree into a planned statement
//---------------------------------------------------------------------------
PlannedStmt *COptTasks::ConvertToPlanStmtFromDXL(CMemoryPool *mp, CMDAccessor *md_accessor, const CDXLNode *dxlnode, bool can_set_tag, DistributionHashOpsKind distribution_hashops) {
	CIdGenerator plan_id_generator(1 /* ulStartId */);
	CIdGenerator motion_id_generator(1 /* ulStartId */);
	CIdGenerator param_id_generator(0 /* ulStartId */);
	List *table_list = NULL; List *subplans_list = NULL;
	CContextDXLToPlStmt dxl_to_plan_stmt_ctxt(mp, &plan_id_generator, &motion_id_generator, &param_id_generator, distribution_hashops, &table_list, &subplans_list);

	// translate DXL -> PlannedStmt
	CTranslatorDXLToPlStmt dxl_to_plan_stmt_translator( mp, md_accessor, &dxl_to_plan_stmt_ctxt, gpdb::GetGPSegmentCount());
	return dxl_to_plan_stmt_translator.GetPlannedStmtFromDXL(dxlnode,
															 can_set_tag);
}

CContextDXLToPlStmt

CContextDXLToPlStmt类提供对CIdGenerators的使用和RangeTableEntries、Subplans的访问。【providing access to CIdGenerators (needed to number initplans, motion nodes as well as params), list of RangeTableEntries and Subplans generated so far during DXL–>PlStmt translation.】
CContextDXLToPlStmt构造函数函数签名为 CContextDXLToPlStmt(CMemoryPool *mp, CIdGenerator *plan_id_counter, CIdGenerator *motion_id_counter, CIdGenerator *param_id_counter, DistributionHashOpsKind distribution_hashops, List **rtable_entries_list, List **subplan_entries_list);为m_plan_id_counter、m_motion_id_counter、m_param_id_counter、m_distribution_hashops、m_subplan_entries_list提供了初始值,初始化m_cte_consumer_info和m_num_partition_selectors_array。

class CContextDXLToPlStmt {
private:
    CMemoryPool *m_mp;
    
	CIdGenerator *m_plan_id_counter; // counter for generating plan ids	
	CIdGenerator *m_motion_id_counter; // counter for generating motion ids	
	CIdGenerator *m_param_id_counter; // counter for generating unique param ids	
	DistributionHashOpsKind m_distribution_hashops; // What operator classes to use for distribution keys?	
	List **m_rtable_entries_list; // list of all rtable entries	
	List **m_subplan_entries_list; // list of all subplan entries

	struct SCTEConsumerInfo{ // cte consumer information	
		List *m_cte_consumer_list; // list of ShareInputScan represent cte consumers	
		SCTEConsumerInfo(List *plan_cte) : m_cte_consumer_list(plan_cte){} // ctor
		void AddCTEPlan(ShareInputScan *share_input_scan) { m_cte_consumer_list = gpdb::LAppend(m_cte_consumer_list, share_input_scan); }
		~SCTEConsumerInfo() { gpdb::ListFree(m_cte_consumer_list); }
	};
	// hash maps mapping ULONG -> SCTEConsumerInfo
	typedef CHashMap<ULONG, SCTEConsumerInfo, gpos::HashValue<ULONG>, gpos::Equals<ULONG>, CleanupDelete<ULONG>,  CleanupDelete<SCTEConsumerInfo> > HMUlCTEConsumerInfo;
	// hash map of the cte identifiers and the cte consumers with the same cte identifier
	HMUlCTEConsumerInfo *m_cte_consumer_info;
	
	
	List *m_partitioned_tables_list; // list of oids of partitioned tables	
	ULongPtrArray *m_num_partition_selectors_array; // number of partition selectors for each dynamic scan
	
	ULONG m_result_relation_index; // index of the target relation in the rtable or 0 if not a DML statement

	IntoClause *m_into_clause; // into clause
	
	GpPolicy *m_distribution_policy; // CTAS distribution policy

public:	
	CContextDXLToPlStmt(CMemoryPool *mp, CIdGenerator *plan_id_counter,CIdGenerator *motion_id_counter,CIdGenerator *param_id_counter,DistributionHashOpsKind distribution_hashops,List **rtable_entries_list,List **subplan_entries_list); // ctor/dtor
	~CContextDXLToPlStmt(); // dtor
	
	ULONG GetNextPlanId() { return m_plan_id_counter->next_id(); }; // retrieve the next plan id	
	ULONG GetCurrentMotionId() { return m_motion_id_counter->current_id(); }; // retrieve the current motion id	
	ULONG GetNextMotionId() { return m_motion_id_counter->next_id(); }; // retrieve the next motion id
	ULONG GetCurrentParamId() { return m_param_id_counter->next_id(); }; // retrieve the current parameter id	
	ULONG GetNextParamId() { return m_param_id_counter->current_id(); }; // retrieve the next parameter id

	// add a newly found CTE consumer
	void AddCTEConsumerInfo(ULONG cte_id, ShareInputScan *share_input_scan);
	// return the list of shared input scan plans representing the CTE consumers
	List *GetCTEConsumerList(ULONG cte_id) const;

	
	List *GetRTableEntriesList() { return (*(m_rtable_entries_list)); }; // return list of range table entries
	// add a range table entry
	void AddRTE(RangeTblEntry *rte, BOOL is_result_relation = false);
	// index of result relation in the rtable
	ULONG GetResultRelationIndex() const { return m_result_relation_index; }	
    void AddSubplan(Plan *);
    List *GetSubplanEntriesList();
    
	// return list of partitioned table indexes
	List *GetPartitionedTablesList() const{ return m_partitioned_tables_list; }
	// return list containing number of partition selectors for every scan id
	List *GetNumPartitionSelectorsList() const;
	// add a partitioned table index
	void AddPartitionedTable(OID oid);
	// increment the number of partition selectors for the given scan id
	void IncrementPartitionSelectors(ULONG scan_id);

	// add CTAS information
	void AddCtasInfo(IntoClause *into_clause, GpPolicy *distribution_policy) { m_into_clause = into_clause; m_distribution_policy = distribution_policy; };
	// into clause
	IntoClause *GetIntoClause() const{ return m_into_clause; }
	// CTAS distribution policy
	GpPolicy * GetDistributionPolicy() const { return m_distribution_policy; }

	// Get the hash opclass or hash function for given datatype, based on decision made by DetermineDistributionHashOpclasses()
	Oid GetDistributionHashOpclassForType(Oid typid);
	Oid GetDistributionHashFuncForType(Oid typid);
};

该类提供如下功能:
1 CIdGenerators的next和current id函数
2 返回RangeTableEntries和subplans generated so far列表,其实就是m_rtable_entries_list和m_subplan_entries_list。
AddRTE函数向m_rtable_entries_list添加RangeTblEntry,如果设置is_result_relation则需要将m_result_relation_index更新为刚加入的RangeTblEntry位置。

//---------------------------------------------------------------------------
//	@function: CContextDXLToPlStmt::AddRTE
//	@doc: Add a RangeTableEntries
//---------------------------------------------------------------------------
void CContextDXLToPlStmt::AddRTE(RangeTblEntry *rte, BOOL is_result_relation){
	(*(m_rtable_entries_list)) = gpdb::LAppend((*(m_rtable_entries_list)), rte);
	rte->inFromCl = true;

	if (is_result_relation) {
		rte->inFromCl = false;
		m_result_relation_index = gpdb::ListLength(*(m_rtable_entries_list));
	}
}

3 AddCTEConsumerInfo需要将share_input_scan包装为cte_plan构造成SCTEConsumerInfo结构体。m_cte_consumer_info是key为cte_id、value为SCTEConsumerInfo的map,因此插入时需要先查找映射关系是否存在。

//---------------------------------------------------------------------------
//	@function:		CContextDXLToPlStmt::AddCTEConsumerInfo
//	@doc:		Add information about the newly found CTE entry
//---------------------------------------------------------------------------
void CContextDXLToPlStmt::AddCTEConsumerInfo(ULONG cte_id, ShareInputScan *share_input_scan) {
	SCTEConsumerInfo *cte_info = m_cte_consumer_info->Find(&cte_id);
	if (NULL != cte_info){
		cte_info->AddCTEPlan(share_input_scan); return;
	}
	List *cte_plan = ListMake1(share_input_scan);
	ULONG *key = GPOS_NEW(m_mp) ULONG(cte_id);
	m_cte_consumer_info->Insert(key, GPOS_NEW(m_mp) SCTEConsumerInfo(cte_plan));
}

//---------------------------------------------------------------------------
//	@function:		CContextDXLToPlStmt::GetCTEConsumerList
//	@doc:	Return the list of GPDB plan nodes representing the CTE consumers		with the given CTE identifier
//---------------------------------------------------------------------------
List *CContextDXLToPlStmt::GetCTEConsumerList(ULONG cte_id) const{
	SCTEConsumerInfo *cte_info = m_cte_consumer_info->Find(&cte_id);
	if (NULL != cte_info){
		return cte_info->m_cte_consumer_list;
	}
	return NULL;
}

4 m_partitioned_tables_list存放的是分区表indexes列表,其中存放的是表oid。

// return list of partitioned table indexes
List *GetPartitionedTablesList() const{ return m_partitioned_tables_list; }
// add a partitioned table oid
void AddPartitionedTable(OID oid){
	if (!gpdb::ListMemberOid(m_partitioned_tables_list, oid)){
		m_partitioned_tables_list = gpdb::LAppendOid(m_partitioned_tables_list, oid);
	}
}

partition_selectors_list存放的是每个scan id中所包含的partition selectors的数量列表,而IncrementPartitionSelectors函数真针对给定scan id 的partition selectors进行递增操作

// return list containing number of partition selectors for every scan id
List *CContextDXLToPlStmt::GetNumPartitionSelectorsList() const{
	List *partition_selectors_list = NIL;
	const ULONG len = m_num_partition_selectors_array->Size();
	for (ULONG ul = 0; ul < len; ul++) {
		ULONG *num_partition_selectors = (*m_num_partition_selectors_array)[ul];
		partition_selectors_list = gpdb::LAppendInt(partition_selectors_list,*num_partition_selectors);
	}
	return partition_selectors_list;
}

// increment the number of partition selectors for the given scan id
void CContextDXLToPlStmt::IncrementPartitionSelectors(ULONG scan_id) {
	// add extra elements to the array if necessary
	const ULONG len = m_num_partition_selectors_array->Size();
	for (ULONG ul = len; ul <= scan_id; ul++){
		ULONG *pul = GPOS_NEW(m_mp) ULONG(0);
		m_num_partition_selectors_array->Append(pul);
	}
	ULONG *ul = (*m_num_partition_selectors_array)[scan_id];
	(*ul)++;
}

CTranslatorDXLToPlStmt

CTranslatorDXLToPlStmt类提供了DXLToPlStmt的转换函数。其构造函数主要是将元数据访问类md_accessor,dxl_to_plstmt_context设置到对应的成员中,同样需要初始化CTranslatorDXLToScalar类,和QueryToDXL流程相似。InitTranslators函数则是初始化对应DXLNode转换为PlStmt的函数。

CTranslatorDXLToPlStmt::CTranslatorDXLToPlStmt(CMemoryPool *mp, CMDAccessor *md_accessor, CContextDXLToPlStmt *dxl_to_plstmt_context, ULONG num_of_segments)
	: m_mp(mp),  m_md_accessor(md_accessor), m_dxl_to_plstmt_context(dxl_to_plstmt_context),  m_cmd_type(CMD_SELECT),  m_is_tgt_tbl_distributed(false), m_result_rel_list(NULL), m_num_of_segments(num_of_segments), m_partition_selector_counter(0){
	m_translator_dxl_to_scalar = GPOS_NEW(m_mp)CTranslatorDXLToScalar(m_mp, m_md_accessor, m_num_of_segments);
	InitTranslators();
}

void CTranslatorDXLToPlStmt::InitTranslators(){
	for (ULONG idx = 0; idx < GPOS_ARRAY_SIZE(m_dxlop_translator_func_mapping_array); idx++) 
		m_dxlop_translator_func_mapping_array[idx] = NULL;

	// array mapping operator type to translator function
	static const STranslatorMapping dxlop_translator_func_mapping_array[] = {
		{EdxlopPhysicalTableScan,
		 &gpopt::CTranslatorDXLToPlStmt::TranslateDXLTblScan},
		{EdxlopPhysicalExternalScan,
		 &gpopt::CTranslatorDXLToPlStmt::TranslateDXLTblScan},
		{EdxlopPhysicalMultiExternalScan,
		 &gpopt::CTranslatorDXLToPlStmt::TranslateDXLTblScan},
		{EdxlopPhysicalIndexScan,
		 &gpopt::CTranslatorDXLToPlStmt::TranslateDXLIndexScan},
		{EdxlopPhysicalIndexOnlyScan,
		 &gpopt::CTranslatorDXLToPlStmt::TranslateDXLIndexOnlyScan},
		{EdxlopPhysicalHashJoin,
		 &gpopt::CTranslatorDXLToPlStmt::TranslateDXLHashJoin},
		{EdxlopPhysicalNLJoin,
		 &gpopt::CTranslatorDXLToPlStmt::TranslateDXLNLJoin},
		{EdxlopPhysicalMergeJoin,
		 &gpopt::CTranslatorDXLToPlStmt::TranslateDXLMergeJoin},
		{EdxlopPhysicalMotionGather,
		 &gpopt::CTranslatorDXLToPlStmt::TranslateDXLMotion},
		{EdxlopPhysicalMotionBroadcast,
		 &gpopt::CTranslatorDXLToPlStmt::TranslateDXLMotion},
		{EdxlopPhysicalMotionRedistribute,
		 &gpopt::CTranslatorDXLToPlStmt::TranslateDXLDuplicateSensitiveMotion},
		{EdxlopPhysicalMotionRandom,
		 &gpopt::CTranslatorDXLToPlStmt::TranslateDXLDuplicateSensitiveMotion},
		{EdxlopPhysicalMotionRoutedDistribute,
		 &gpopt::CTranslatorDXLToPlStmt::TranslateDXLMotion},
		{EdxlopPhysicalLimit,
		 &gpopt::CTranslatorDXLToPlStmt::TranslateDXLLimit},
		{EdxlopPhysicalAgg, &gpopt::CTranslatorDXLToPlStmt::TranslateDXLAgg},
		{EdxlopPhysicalWindow,
		 &gpopt::CTranslatorDXLToPlStmt::TranslateDXLWindow},
		{EdxlopPhysicalSort, &gpopt::CTranslatorDXLToPlStmt::TranslateDXLSort},
		{EdxlopPhysicalSubqueryScan,
		 &gpopt::CTranslatorDXLToPlStmt::TranslateDXLSubQueryScan},
		{EdxlopPhysicalResult,
		 &gpopt::CTranslatorDXLToPlStmt::TranslateDXLResult},
		{EdxlopPhysicalAppend,
		 &gpopt::CTranslatorDXLToPlStmt::TranslateDXLAppend},
		{EdxlopPhysicalMaterialize,
		 &gpopt::CTranslatorDXLToPlStmt::TranslateDXLMaterialize},
		{EdxlopPhysicalSequence,
		 &gpopt::CTranslatorDXLToPlStmt::TranslateDXLSequence},
		{EdxlopPhysicalDynamicTableScan,
		 &gpopt::CTranslatorDXLToPlStmt::TranslateDXLDynTblScan},
		{EdxlopPhysicalDynamicIndexScan,
		 &gpopt::CTranslatorDXLToPlStmt::TranslateDXLDynIdxScan},
		{EdxlopPhysicalTVF, &gpopt::CTranslatorDXLToPlStmt::TranslateDXLTvf},
		{EdxlopPhysicalDML, &gpopt::CTranslatorDXLToPlStmt::TranslateDXLDml},
		{EdxlopPhysicalSplit,
		 &gpopt::CTranslatorDXLToPlStmt::TranslateDXLSplit},
		{EdxlopPhysicalRowTrigger,
		 &gpopt::CTranslatorDXLToPlStmt::TranslateDXLRowTrigger},
		{EdxlopPhysicalAssert,
		 &gpopt::CTranslatorDXLToPlStmt::TranslateDXLAssert},
		{EdxlopPhysicalCTEProducer,
		 &gpopt::CTranslatorDXLToPlStmt::TranslateDXLCTEProducerToSharedScan},
		{EdxlopPhysicalCTEConsumer,
		 &gpopt::CTranslatorDXLToPlStmt::TranslateDXLCTEConsumerToSharedScan},
		{EdxlopPhysicalBitmapTableScan,
		 &gpopt::CTranslatorDXLToPlStmt::TranslateDXLBitmapTblScan},
		{EdxlopPhysicalDynamicBitmapTableScan,
		 &gpopt::CTranslatorDXLToPlStmt::TranslateDXLBitmapTblScan},
		{EdxlopPhysicalCTAS, &gpopt::CTranslatorDXLToPlStmt::TranslateDXLCtas},
		{EdxlopPhysicalPartitionSelector,
		 &gpopt::CTranslatorDXLToPlStmt::TranslateDXLPartSelector},
		{EdxlopPhysicalValuesScan,
		 &gpopt::CTranslatorDXLToPlStmt::TranslateDXLValueScan},
	};

	const ULONG num_of_translators =GPOS_ARRAY_SIZE(dxlop_translator_func_mapping_array);
	for (ULONG idx = 0; idx < num_of_translators; idx++){
		STranslatorMapping elem = dxlop_translator_func_mapping_array[idx];
		m_dxlop_translator_func_mapping_array[elem.dxl_op_id] = elem.dxlnode_to_logical_funct;
	}
}

GetPlannedStmtFromDXL

实现Translate DXL node into a PlannedStmt功能的入口函数:1 初始化CDXLTranslateContext dxl_translate_ctxt和CDXLTranslationContextArray *ctxt_translation_prev_siblings 2 调用TranslateDXLOperatorToPlan(dxlnode, &dxl_translate_ctxt, ctxt_translation_prev_siblings)进行转换【TranslateDXLOperatorToPlan函数根据dxlnode->GetOperator()->GetDXLOperator()不同的操作符id获取对应的转换函数,并调用转换函数进行转换】3 将所有的RangeTblEntry中的RTE_RELATION的oid从RangeTblEntry提取出来放到oids_list中
4 组装planned stmt 5 如果是CMD_SELECT,且dxlnode中的m_direct_dispatch_info不为null,说明该执行计划可以进行direct dispath给某个segment,因此需要设置plan中的directDispatch信息,比如dispath的segment contentId列表,将planned_stmt->planTree中的Motion节点都设置directDispatch信息。

PlannedStmt *CTranslatorDXLToPlStmt::GetPlannedStmtFromDXL(const CDXLNode *dxlnode,  bool can_set_tag) {
	CDXLTranslateContext dxl_translate_ctxt(m_mp, false);
	CDXLTranslationContextArray *ctxt_translation_prev_siblings = GPOS_NEW(m_mp) CDXLTranslationContextArray(m_mp);
	
	Plan *plan = TranslateDXLOperatorToPlan(dxlnode, &dxl_translate_ctxt, ctxt_translation_prev_siblings);
	ctxt_translation_prev_siblings->Release();

	// collect oids from rtable
	List *oids_list = NIL;ListCell *lc_rte = NULL;
	ForEach(lc_rte, m_dxl_to_plstmt_context->GetRTableEntriesList()){
		RangeTblEntry *pRTE = (RangeTblEntry *) lfirst(lc_rte);
		if (pRTE->rtekind == RTE_RELATION){
			oids_list = gpdb::LAppendOid(oids_list, pRTE->relid);
		}
	}

	// assemble planned stmt
	PlannedStmt *planned_stmt = MakeNode(PlannedStmt); planned_stmt->planGen = PLANGEN_OPTIMIZER;
	planned_stmt->rtable = m_dxl_to_plstmt_context->GetRTableEntriesList();
	planned_stmt->subplans = m_dxl_to_plstmt_context->GetSubplanEntriesList();
	planned_stmt->planTree = plan;
	// store partitioned table indexes in planned stmt
	planned_stmt->queryPartOids = m_dxl_to_plstmt_context->GetPartitionedTablesList();
	planned_stmt->canSetTag = can_set_tag;
	planned_stmt->relationOids = oids_list;
	planned_stmt->numSelectorsPerScanId = m_dxl_to_plstmt_context->GetNumPartitionSelectorsList();
	plan->nMotionNodes = m_dxl_to_plstmt_context->GetCurrentMotionId() - 1;
	planned_stmt->nMotionNodes = m_dxl_to_plstmt_context->GetCurrentMotionId() - 1;
	planned_stmt->commandType = m_cmd_type;
	if (0 == plan->nMotionNodes && !m_is_tgt_tbl_distributed){
		// no motion nodes and not a DML on a distributed table
		plan->dispatch = DISPATCH_SEQUENTIAL;
	}else{
		plan->dispatch = DISPATCH_PARALLEL;
	}
	planned_stmt->resultRelations = m_result_rel_list;
	// GPDB_92_MERGE_FIXME: we really *should* be handling intoClause
	// but currently planner cheats (c.f. createas.c)
	// shift the intoClause handling into planner and re-enable this
	//	pplstmt->intoClause = m_pctxdxltoplstmt->Pintocl();
	planned_stmt->intoPolicy = m_dxl_to_plstmt_context->GetDistributionPolicy();

	SetInitPlanVariables(planned_stmt);

	if (CMD_SELECT == m_cmd_type && NULL != dxlnode->GetDXLDirectDispatchInfo()){
		List *direct_dispatch_segids = TranslateDXLDirectDispatchInfo(dxlnode->GetDXLDirectDispatchInfo());
		plan->directDispatch.contentIds = direct_dispatch_segids;
		plan->directDispatch.isDirectDispatch = (NIL != direct_dispatch_segids);
		if (plan->directDispatch.isDirectDispatch){
			List *motion_node_list = gpdb::ExtractNodesPlan(planned_stmt->planTree, T_Motion,  true /*descendIntoSubqueries*/);
			ListCell *lc = NULL;
			ForEach(lc, motion_node_list){
				Motion *motion = (Motion *) lfirst(lc);
				motion->plan.directDispatch.isDirectDispatch = true;
				motion->plan.directDispatch.contentIds = plan->directDispatch.contentIds;
			}
		}
	}

	return planned_stmt;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/909451.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

LION AI 大模型落地,首搭星纪元 ES

自新能源汽车蓬勃发展以来&#xff0c;随着潮流不断进步和变革的“四大件”有着明显变化。其中有&#xff1a;平台、智能驾驶、配置、以及车机。方方面面都有着不同程度的革新。 而车机方面&#xff0c;从以前老旧的媒体机、 CD 机发展至如今具有拓展性、开放性、智能化的车机…

Quartz任务调度框架介绍和使用

一、Quartz介绍 Quartz [kwɔːts] 是OpenSymphony开源组织在Job scheduling领域又一个开源项目&#xff0c;完全由Java开发&#xff0c;可以用来执行定时任务&#xff0c;类似于java.util.Timer。但是相较于Timer&#xff0c; Quartz增加了很多功能&#xff1a; 1.持久性作业 …

物联网(IoT)安全挑战与解决方案: 分析物联网设备面临的安全威胁,以及如何设计和管理安全的IoT生态系统

第一章&#xff1a;引言 随着科技的飞速发展&#xff0c;物联网&#xff08;IoT&#xff09;作为连接世界的桥梁&#xff0c;已经成为现代社会不可或缺的一部分。然而&#xff0c;随着IoT设备数量的不断增加&#xff0c;其安全问题也日益显著。本文将深入探讨IoT领域面临的安全…

【Ubuntu20.04安装Nvidia驱动、CUDA和CUDNN】

Ubuntu20.04安装Nvidia驱动、CUDA和CUDNN 1 Nvidia驱动安装1.1 安装1.2 安装Nvidia可能会遇到的问题1.2.1 NVIDIA 驱动与 Nouveau 驱动不兼容1.2.2 ERROR: Unable to find the development tool cc 2 CUDA安装2.1 下载和安装2.2 配置CUDA环境 3 安装CUDNN4 切换CUDA版本 1 Nvid…

min-height到底是什么?

1、概念 给元素设置最小高度&#xff0c;当height小于 min-height &#xff0c;min-height会覆盖height的值 2、案例 如果我有一个盒子A&#xff0c;A设置了min-height的高度为200px&#xff1b;并设置了overflow&#xff1a;auto&#xff0c;那么如果里面的内容超过了200px…

【经验】VScode 远程连接 Ubuntu 出错,Could not establish connection

用VScode常常会碰到以下情况&#xff0c;Could not establish connection。 先介绍一下VScode远程连接和终端SSH连接的区别&#xff1a;终端直接用SSH连接时&#xff0c;只需要开启SSH服务&#xff0c;并消耗少量的内存即可&#xff1b;VScode连接时&#xff0c;会自动在服务器…

MySQL基础篇 (三)

函数 回顾学过的函数 countavgsumminmax 数值函数 做数值运算的 演示 #ABS(X)SELECT ABS(0); #SIGN(X)SELECT SIGN(-10); #SQRT(X)SELECT SQRT(4); #LEAST(value1,value2,...)SELECT LEAST(10,20,15);字符串函数 做字符串处理&#xff08;CONCAT()&#xff09; 演示 #CO…

HCIP学习--三层架构

未完成 网关作为了一个广播域的中心出口&#xff1b;生成树的根网桥也是一棵树的中心&#xff0c;也是流量的集合点&#xff1b; 若将两者分配不同的设备将导致网络通讯资源浪费&#xff0c;故强烈建议两者在同一台汇聚层设备上 举个例子 看下图若VLAN2要去找VLAN3设备需要…

java+springboot+mysql医院预约挂号管理系统

项目介绍&#xff1a; 使用javaspringbootmysql开发的医院预约挂号管理系统&#xff0c;系统包含超级管理员、管理员、医生、患者角色&#xff0c;功能如下&#xff1a; 超级管理员&#xff1a;管理员管理&#xff1b;用户管理&#xff1b;科室管理&#xff1b;床位管理&…

问道管理:沪指弱势震荡跌0.38%,金融、地产等板块走弱,算力概念等活跃

21日早盘&#xff0c;沪指盘中弱势震荡下探&#xff0c;创业板指一度跌逾1%失守2100点&#xff1b;北向资金小幅净流出。 截至午间收盘&#xff0c;沪指跌0.38%报3120.18点&#xff0c;深成指跌0.24%&#xff0c;创业板指跌0.62%&#xff1b;两市算计成交4238亿元&#xff0c;…

钛合金为何成为iPhone 15 Pro材料首选?

多年来&#xff0c;iPhone Pro一直采用厚重的钢框架&#xff0c;但不会持续太久。 有了iPhone 15 Pro&#xff0c;苹果可能会从钢框架转向钛框架&#xff0c;这不仅仅是因为它听起来更酷。钛比钢有很多优点&#xff0c;尤其是它更轻&#xff0c;这将解决iPhone Pro与普通iPhon…

Nvidia Jetson 编解码开发(3)解决H265解码报错“PPS id out of range”

1.问题描述 基于之前的开发程序 Nvidia Jetson 编解码开发(2)Jetpack 4.x版本Multimedia API 硬件编码开发--集成encode模块_free-xx的博客-CSDN博客 通过Jetson Xavier NX 硬编码的H265发出后, 上位机断点播放发出来的H265码流, 会报“PPS id out of range” 错误 …

有没有免费格式转换工具推荐?PDF转化为PPT的方法

在当今职场生活中&#xff0c;掌握文件格式转换技能变得异常重要。将PDF文档转换为PPT格式可以在演讲、报告等场合更好地展示和传达信息&#xff0c;为我们的专业形象增添亮点&#xff0c;接下来我们可以一起来看一下“有没有免费格式转换工具推荐?PDF转化为PPT的方法”相关的…

使用kubeadm安装和设置Kubernetes(k8s)

用kubeadm方式搭建K8S集群 kubeadm是官方社区推出的一个用于快速部署kubernetes集群的工具。 这个工具能通过两条指令完成一个kubernetes集群的部署&#xff1a; # 创建一个 Master 节点 kubeadm init# 将一个 Node 节点加入到当前集群中 kubeadm join <Master节点的IP和端口…

2023 网络建设与运维 X86架构计算机操作系统安装与管理题解

任务描述: 随着信息技术的快速发展,集团计划2023年把部分业务由原有的X86架构服务器上迁移到ARM架构服务器上,同时根据目前的部分业务需求进行了部分调整和优化。 一、X86架构计算机操作系统安装与管理 1.PC1系统为ubuntu-desktop-amd64系统(已安装,语言为英文),登录用户…

基于深度学习的图像风格迁移发展总结

前言 本文总结深度学习领域的图像风格迁移发展脉络。重点关注随着GAN、CUT、StyleGAN、CLIP、Diffusion Model 这些网络出现以来&#xff0c;图像风格迁移在其上的发展。本文注重这些网络对图像风格迁移任务的影响&#xff0c;以及背后的关键技术和研究&#xff0c;并总结出一…

*看门狗1

//while部分是我们在项目中具体需要写的代码&#xff0c;这部分的程序可以用独立看门狗来监控 //如果我们知道这部分代码的执行时间&#xff0c;比如是500ms&#xff0c;那么我们可以设置独立看门狗的 //溢出时间是600ms&#xff0c;比500ms多一点&#xff0c;如果要被监控的程…

解决`java.lang.NoClassDefFoundError`在Nacos和Spring Boot集成中的问题

&#x1f337;&#x1f341; 博主猫头虎 带您 Go to New World.✨&#x1f341; &#x1f984; 博客首页——猫头虎的博客&#x1f390; &#x1f433;《面试题大全专栏》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33a; &a…

财务数据分析用什么软件好?奥威BI自带方案

做财务数据分析&#xff0c;光有软件还不够&#xff0c;还需要有标准化的智能财务数据分析方案。奥威BI数据可视化工具就是这样一款自带智能财务数据分析方案的软件。 ”BI方案“&#xff0c;一站式做财务数据分析 奥威BI数据可视化工具和智能财务分析方案结合&#xff0c;可…

一套基于C#语言开发的LIMS实验室信息管理系统源码

实验室信息管理系统&#xff08;LIMS)是指帮助实验室组织和管理实验数据的计算机软件系统&#xff0c;它将实验室操作有机地组织在一起&#xff0c;以满足实验室工作流程的所有要求。它能以不同的方式支持实验室的工作&#xff0c;从简单的过程(如样品采集和入库)到复杂的流程(…