Spark Core--加强

RDD的持久化

在这里插入图片描述

RDD缓存

当RDD被重复使用,或者计算该RDD比较容易出错,而且需要消耗比较多的资源和时间的时候,我们就可以将该RDD缓存起来。

主要作用: 提升Spark程序的计算效率
注意事项: RDD的缓存可以存储在内存或者是磁盘上,甚至可以存储在Executor进程的堆外内存中。主要是放在内存中,因此缓存的数据是不太稳定可靠。

由于是临时存储,可能会存在丢失,所以缓存操作,并不会将RDD之间的依赖关系给截断掉(丢失掉),因为当缓存
失效后,可以全部重新计算
缓存的API都是Lazy惰性的,如果需要触发缓存操作,推荐调用count算子,因为运行效率高

设置缓存的API: 
	rdd.cache(): 将RDD的数据缓存储内存中
	rdd.persist(缓存的级别/位置): 将RDD的数据存储在指定位置

手动清理缓存API:
	rdd.unpersist()
默认情况下,当整个Spark应用程序执行完成后,缓存数据会自动失效,会被自动删除

缓存的级别/位置:
    DISK_ONLY: 只存储在磁盘
    DISK_ONLY_2: 只存储在磁盘,并且有2个副本
    DISK_ONLY_3: 只存储在磁盘,并且有3个副本
    MEMORY_ONLY: 只存储在内存中
    MEMORY_ONLY_2: 只存储在内存中,并且有2个副本
    MEMORY_AND_DISK: 存储在内存和磁盘中,先放在内存,再放在磁盘
    MEMORY_AND_DISK_2: 存储在内存和磁盘中,先放在内存,再放在磁盘,并且有2个副本
    OFF_HEAP: Executor进程的堆外内存
    
工作中最常用的是: MEMORY_AND_DISK和MEMORY_AND_DISK_2。优先推荐使用MEMORY_AND_DISK

演示缓存的使用操作:

import time

from pyspark import SparkConf, SparkContext, StorageLevel
import os
import jieba

# 绑定指定的Python解释器
os.environ['SPARK_HOME'] = '/export/server/spark'
os.environ['PYSPARK_PYTHON'] = '/root/anaconda3/bin/python3'
os.environ['PYSPARK_DRIVER_PYTHON'] = '/root/anaconda3/bin/python3'

# 需要过滤的关键词黑名单
keyword_black_list = ['+','.','的','com']

# ctrl+alt+M将代码封装成函数/方法
# 3.2- 需求一:统计每个关键词出现了多少次。先提取需要操作的字段并且分词,这一步类似WordCount中的对每行进行切分处理,再仿照WordCount实现。
def top10_keyword():
    keyword_rdd = etl_rdd.flatMap(lambda line_tup: list(jieba.cut(line_tup[2])))
    # print(keyword_rdd.take(10))

    # 数据结构转变。将单词变成元组
    # keyword_map_rdd = keyword_rdd.filter(lambda word:word!='+' or word!='.').map(lambda word:(word,1))
    keyword_map_rdd = keyword_rdd.filter(lambda word: word not in keyword_black_list).map(lambda word: (word, 1))

    # 分组聚合操作
    keyword_result_rdd = keyword_map_rdd.reduceByKey(lambda agg, curr: agg + curr)
    # print(keyword_result_rdd.take(100))

    # 对结果中关键词的次数降序排序,取TOP10
    keyword_result = keyword_result_rdd.top(10, key=lambda tup: tup[1])
    print(keyword_result)


# 3.3- 需求二:统计每个用户每个搜索内容点击的次数
def content():
    # 从原始的6个字段中,提取出2个字段,得到 (用户,搜索内容)
    new_tup_tmp_rdd = etl_rdd.map(lambda tup: (tup[1], tup[2]))

    # 数据格式转换
    """
            输入:(张三,鸡你太美) -> hello
            输出:((张三,鸡你太美),1) -> (hello,1)
        """
    new_tup_rdd = new_tup_tmp_rdd.map(lambda tup: (tup, 1))
    # new_tup_rdd = new_tup_tmp_rdd.map(lambda tup:(tup[0],tup[1],1))

    # 分组聚合
    content_result = new_tup_rdd.reduceByKey(lambda agg, curr: agg + curr)
    print(content_result.take(10))


if __name__ == '__main__':

    # 1- 创建SparkContext
    conf = SparkConf().setAppName('sogou_demo').setMaster('local[*]')
    sc = SparkContext(conf=conf)

    # 2- 数据输入
    init_rdd = sc.textFile('file:///export/data/spark_core/data/SogouQ.sample')

    print("ETL处理前数据条数:",init_rdd.count())

    # 3- 数据处理
    # 3.1- ETL:数据的清洗、转换、加载
    """
        split():默认按照空白字符进行切分。例如:空格、制表符、回车换行符等
        
        map和flatMap的主要区别:flatMap对每一个元素处理以后,会将结果打平/压扁到一个更大的容器当中。
    """
    map_rdd = init_rdd.map(lambda line:line.split())
    # print("调用map算子后的内容:",map_rdd.take(10))

    # flatmap_rdd = init_rdd.flatMap(lambda line: line.split())
    # print("调用flatMap算子后的内容:",flatmap_rdd.take(10))

    # 过滤掉每行中没有6个字段的数据
    filter_rdd = map_rdd.filter(lambda line_list: len(line_list)==6)


    # 数据结构转换(为了演示而演示)
    etl_rdd = filter_rdd.map(lambda line_list:(
        line_list[0],
        line_list[1],
        line_list[2][1:-1], # 省略前后的中括号
        line_list[3],
        line_list[4],
        line_list[5]
    ))

    # 设置缓存。并且调用count算子触发操作
    # etl_rdd.cache().count()
    etl_rdd.persist(storageLevel=StorageLevel.MEMORY_AND_DISK).count()

    print("ETL处理后数据条数:", etl_rdd.count())

    # 3.2- 需求一:统计每个关键词出现了多少次
    # top10_keyword()

    # 3.3- 需求二:统计每个用户每个搜索内容点击的次数
    content()
    time.sleep(20)

    # 手动清理缓存。你对哪个RDD设置了缓存,那么你就对那个RDD清理缓存。也需要调用count算子触发。
    etl_rdd.unpersist().count()
    time.sleep(100)
    # 5- 释放资源
    sc.stop()

无缓存的DAG流程图显示:
在这里插入图片描述
有缓存的DAG流程图显示:
在这里插入图片描述
在这里插入图片描述

RDD的checkpoint检查点

RDD缓存主要是将数据存储在内存中,是临时存储,不太稳定,它主要是用来提升程序运行效率的。RDD的checkpoint(检查点)主要是将数据存储在HDFS上,是持久化存储。而HDFS存储数据有3副本的机制,让数据更加安全可靠。

checkpoint认为使用磁盘或者HDFS存储数据之后,数据非常的安全可靠,因此checkpoint会将RDD间的依赖关系给删除/丢弃掉。因此如果checkpoint的数据真的出现了问题,是无法在从头开始计算。

checkpoint主要作用: 提高程序的容错性
注意事项: checkpoint可以将数据存储在磁盘或者HDFS上,主要是将数据存储在HDFS上。

相关API:
sc.setCheckpointDir(存储路径): 设置checkpoint数据存放路径
rdd.checkpoint(): 对指定RDD启用checkpoint
rdd.count(): 触发checkpoint

代码演示:

import time

from pyspark import SparkConf, SparkContext, StorageLevel
import os
import jieba

# 绑定指定的Python解释器
os.environ['SPARK_HOME'] = '/export/server/spark'
os.environ['PYSPARK_PYTHON'] = '/root/anaconda3/bin/python3'
os.environ['PYSPARK_DRIVER_PYTHON'] = '/root/anaconda3/bin/python3'

# 需要过滤的关键词黑名单
keyword_black_list = ['+','.','的','com']

# ctrl+alt+M将代码封装成函数/方法
# 3.2- 需求一:统计每个关键词出现了多少次。先提取需要操作的字段并且分词,这一步类似WordCount中的对每行进行切分处理,再仿照WordCount实现。
def top10_keyword():
    keyword_rdd = etl_rdd.flatMap(lambda line_tup: list(jieba.cut(line_tup[2])))
    # print(keyword_rdd.take(10))

    # 数据结构转变。将单词变成元组
    # keyword_map_rdd = keyword_rdd.filter(lambda word:word!='+' or word!='.').map(lambda word:(word,1))
    keyword_map_rdd = keyword_rdd.filter(lambda word: word not in keyword_black_list).map(lambda word: (word, 1))

    # 分组聚合操作
    keyword_result_rdd = keyword_map_rdd.reduceByKey(lambda agg, curr: agg + curr)
    # print(keyword_result_rdd.take(100))

    # 对结果中关键词的次数降序排序,取TOP10
    keyword_result = keyword_result_rdd.top(10, key=lambda tup: tup[1])
    print(keyword_result)


# 3.3- 需求二:统计每个用户每个搜索内容点击的次数
def content():
    # 从原始的6个字段中,提取出2个字段,得到 (用户,搜索内容)
    new_tup_tmp_rdd = etl_rdd.map(lambda tup: (tup[1], tup[2]))

    # 数据格式转换
    """
            输入:(张三,鸡你太美) -> hello
            输出:((张三,鸡你太美),1) -> (hello,1)
        """
    new_tup_rdd = new_tup_tmp_rdd.map(lambda tup: (tup, 1))
    # new_tup_rdd = new_tup_tmp_rdd.map(lambda tup:(tup[0],tup[1],1))

    # 分组聚合
    content_result = new_tup_rdd.reduceByKey(lambda agg, curr: agg + curr)
    print(content_result.take(10))


if __name__ == '__main__':

    # 1- 创建SparkContext
    conf = SparkConf().setAppName('sogou_demo').setMaster('local[*]')
    sc = SparkContext(conf=conf)

    # 设置checkpoint路径
    sc.setCheckpointDir("hdfs://node1:8020/chk")

    # 2- 数据输入
    init_rdd = sc.textFile('file:///export/data/spark_core/data/SogouQ.sample')

    print("ETL处理前数据条数:",init_rdd.count())

    # 3- 数据处理
    # 3.1- ETL:数据的清洗、转换、加载
    """
        split():默认按照空白字符进行切分。例如:空格、制表符、回车换行符等
        
        map和flatMap的主要区别:flatMap对每一个元素处理以后,会将结果打平/压扁到一个更大的容器当中。
    """
    map_rdd = init_rdd.map(lambda line:line.split())
    # print("调用map算子后的内容:",map_rdd.take(10))

    # flatmap_rdd = init_rdd.flatMap(lambda line: line.split())
    # print("调用flatMap算子后的内容:",flatmap_rdd.take(10))

    # 过滤掉每行中没有6个字段的数据
    filter_rdd = map_rdd.filter(lambda line_list: len(line_list)==6)


    # 数据结构转换(为了演示而演示)
    etl_rdd = filter_rdd.map(lambda line_list:(
        line_list[0],
        line_list[1],
        line_list[2][1:-1], # 省略前后的中括号
        line_list[3],
        line_list[4],
        line_list[5]
    ))

    # 对指定RDD启用checkpoint
    etl_rdd.checkpoint()
    # 调用count算子,触发checkpoint操作
    etl_rdd.count()
    print("ETL处理后数据条数:", etl_rdd.count())

    # 3.2- 需求一:统计每个关键词出现了多少次
    # top10_keyword()

    # 3.3- 需求二:统计每个用户每个搜索内容点击的次数
    content()
    time.sleep(1000)
    # 5- 释放资源
    sc.stop()

没有设置检查点正常的DAG执行流图:
在这里插入图片描述
设置检查点后:

在这里插入图片描述

缓存和checkpoint的区别

1- 数据存储位置不同
缓存: 存储在内存或者磁盘 或者 堆外内存中
checkpoint检查点: 可以将数据存储在磁盘或者HDFS上, 在集群模式下, 仅能保存到HDFS上

2- 数据生命周期:
缓存: 当程序执行完成后, 或者手动调用unpersist 缓存都会被删除
checkpoint检查点: 即使程序退出后, checkpoint检查点的数据依然是存在的, 不会删除, 需要手动删除

3- 血缘关系:
缓存: 不会截断RDD之间的血缘关系, 因为缓存数据有可能是失效, 当失效后, 需要重新回溯计算操作
checkpoint检查点: 会截断掉依赖关系, 因为checkpoint将数据保存到更加安全可靠的位置, 不会发生数据丢失的问题, 当执行失败的时候, 也不需要重新回溯执行

4- 主要作用不同
缓存: 提高Spark程序的运行效率
checkpoint检查点: 提高Spark程序的容错性

思考:既然持久化的方案有两种,那么在生产环境中应该使用哪种方案呢?

在同一个项目中,推荐缓存和checkpoint(检查点)同时配合使用。

使用顺序如下: 在代码中先设置缓存,再设置checkpoint检查点,然后再一同使用Action算子触发,推荐使用count算子。因为这个顺序,只会有一次IO写的过程。

实际过程如下: 程序会优先从缓存中读取数据,如果发现缓存中没有数据。再从checkpoint中读取数据,并且接着将读取到的数据重新在内存中放置一份,后续还是优先从缓存中读取

在这里插入图片描述
测试:

import time

from pyspark import SparkConf, SparkContext, StorageLevel
import os
import jieba

# 绑定指定的Python解释器
os.environ['SPARK_HOME'] = '/export/server/spark'
os.environ['PYSPARK_PYTHON'] = '/root/anaconda3/bin/python3'
os.environ['PYSPARK_DRIVER_PYTHON'] = '/root/anaconda3/bin/python3'

# 需要过滤的关键词黑名单
keyword_black_list = ['+','.','的','com']

# ctrl+alt+M将代码封装成函数/方法
# 3.2- 需求一:统计每个关键词出现了多少次。先提取需要操作的字段并且分词,这一步类似WordCount中的对每行进行切分处理,再仿照WordCount实现。
def top10_keyword():
    keyword_rdd = etl_rdd.flatMap(lambda line_tup: list(jieba.cut(line_tup[2])))
    # print(keyword_rdd.take(10))

    # 数据结构转变。将单词变成元组
    # keyword_map_rdd = keyword_rdd.filter(lambda word:word!='+' or word!='.').map(lambda word:(word,1))
    keyword_map_rdd = keyword_rdd.filter(lambda word: word not in keyword_black_list).map(lambda word: (word, 1))

    # 分组聚合操作
    keyword_result_rdd = keyword_map_rdd.reduceByKey(lambda agg, curr: agg + curr)
    # print(keyword_result_rdd.take(100))

    # 对结果中关键词的次数降序排序,取TOP10
    keyword_result = keyword_result_rdd.top(10, key=lambda tup: tup[1])
    print(keyword_result)


# 3.3- 需求二:统计每个用户每个搜索内容点击的次数
def content():
    # 从原始的6个字段中,提取出2个字段,得到 (用户,搜索内容)
    new_tup_tmp_rdd = etl_rdd.map(lambda tup: (tup[1], tup[2]))

    # 数据格式转换
    """
            输入:(张三,鸡你太美) -> hello
            输出:((张三,鸡你太美),1) -> (hello,1)
        """
    new_tup_rdd = new_tup_tmp_rdd.map(lambda tup: (tup, 1))
    # new_tup_rdd = new_tup_tmp_rdd.map(lambda tup:(tup[0],tup[1],1))

    # 分组聚合
    content_result = new_tup_rdd.reduceByKey(lambda agg, curr: agg + curr)
    print(content_result.take(10))


if __name__ == '__main__':

    # 1- 创建SparkContext
    conf = SparkConf().setAppName('sogou_demo').setMaster('local[*]')
    sc = SparkContext(conf=conf)

    # 设置checkpoint路径
    sc.setCheckpointDir("hdfs://node1:8020/chk")

    # 2- 数据输入
    init_rdd = sc.textFile('file:///export/data/spark_core/data/SogouQ.sample')

    print("ETL处理前数据条数:",init_rdd.count())

    # 3- 数据处理
    # 3.1- ETL:数据的清洗、转换、加载
    """
        split():默认按照空白字符进行切分。例如:空格、制表符、回车换行符等
        
        map和flatMap的主要区别:flatMap对每一个元素处理以后,会将结果打平/压扁到一个更大的容器当中。
    """
    map_rdd = init_rdd.map(lambda line:line.split())
    # print("调用map算子后的内容:",map_rdd.take(10))

    # flatmap_rdd = init_rdd.flatMap(lambda line: line.split())
    # print("调用flatMap算子后的内容:",flatmap_rdd.take(10))

    # 过滤掉每行中没有6个字段的数据
    filter_rdd = map_rdd.filter(lambda line_list: len(line_list)==6)

    # 数据结构转换(为了演示而演示)
    etl_rdd = filter_rdd.map(lambda line_list:(
        line_list[0],
        line_list[1],
        line_list[2][1:-1], # 省略前后的中括号
        line_list[3],
        line_list[4],
        line_list[5]
    ))

    # 先缓存
etl_rdd.persist(storageLevel=StorageLevel.MEMORY_AND_DISK)
    # 再checkpoint
    etl_rdd.checkpoint()
    # 最后调用count算子,一同触发
    etl_rdd.count()
    
    print("ETL处理后数据条数:", etl_rdd.count())

    # 3.2- 需求一:统计每个关键词出现了多少次
    # top10_keyword()
    # 3.3- 需求二:统计每个用户每个搜索内容点击的次数
    content()
    time.sleep(1000)
    # 5- 释放资源
    sc.stop()

DAG有向无环图:
在这里插入图片描述

Spark内核调度

RDD的依赖

RDD依赖:一个RDD的形成可能是由一个或者多个RDD得到的,此时这个RDD和之前的RDD之间产生依赖关系。

在Spark中,RDD之间的依赖关系,主要有二种类型:

  • 窄依赖
作用: 能够让Spark程序并行计算。也就是一个分区数据计算出现问题以后,其他的分区计算不受到任何影响

特点: 父RDD的分区和子RDD的分区关系是一对一的关系。
也就是父RDD分区的数据会整个被下游子RDD的分区接收

在这里插入图片描述

  • 宽依赖
作用: 划分Stage的重要依据。宽依赖也叫做Shuffle依赖
特点: 父RDD的分区和子RDD的分区关系是一对多的关系。也就是父RDD的分区数据会被分成多份给到下游子RDD的多个分区所接收。

注意: 如果有宽依赖,shuffle下游的其他操作,必须等待shuffle执行完成以后才能够继续执行。为了避免数据不完整

在这里插入图片描述

在实际使用中,不需要纠结哪些算子会存在shuffle,以需求为目标**。虽然shuffle的存在会影响一定的效率, 但是以完成任务为准则,**该用那个算子,就使用那个算子即可,不要过分纠结。	

算子中一般以ByKey结尾的会发生shuffle;另外是重分区算子会发生shuffle

DAG和Stage

DAG:有向无环图,主要描述一段执行任务,从开始一直往下走,不允许出现回调操作

Spark应用程序中,遇到一个Action算子,就会触发形成一个Job任务的产生。

对于每一个Job的任务,都会产生一个DAG执行流程图,那么这个流程图是如何形成的呢?

层级关系:
1- 一个Spark应用程序 -> 遇到一个Action算子,就会触发形成一个Job任务
2- 一个Job任务只有一个DAG有向无环图
3- 一个DAG有向无环图 -> 有多个Stage
4- 一个Stage -> 有多个Task线程
5- 一个RDD -> 有多个分区
6- 一个分区会被一个Task线程所处理

DAG执行流程图形成和Stage划分:
在这里插入图片描述

1- Spark应用程序遇到Action算子后,就会触发一个Job任务的产生。Job任务会将它所依赖的所有算子全部加载进来,形成一个Stage

2- 接着从Action算子从后往前进行回溯,遇到窄依赖就将算子放在同一个Stage当中;如果遇到宽依赖,就划分形成新的Stage。最后一直回溯完成

细化剖析Stage内部的流程:
在这里插入图片描述
默认并行度的值确认:

因为是使用textFile读取HDFS上的文件,因此RDD分区数=max(文件的block块的数量, defaultMinPartition)。继续需要知道defaultMinPartition的值是多少。

defaultMinPartition=min(spark.default.parallelism,2)取最小值。最终我们确认spark.default.parallelism的参数值就能够最终确认RDD的分区数有多少个

spark.default.parallelism参数值确认过程如下:
1- 如果有父RDD,就取父RDD的最大分区数
2- 如果没有父RDD,根据集群模式进行取值:
   2.1- 本地模式:机器的最大CPU核数
   2.2- (了解)Mesos:默认是8
   2.3- 其他模式:所有执行节点上的核总数或2,以较大者为准

Spark Shuffle

Spark中shuffle的发展历程:

1- 在1.1版本以前,Spark采用Hash shuffle (优化前 和 优化后)

2- 在1.1版本的时候,Spark推出了Sort Shuffle

3- 在1.5版本的时候,Spark引入钨丝计划(优化为主)

4- 在1.6版本的时候,将钨丝计划合并到sortShuffle中

5- 在2.0版本的时候,将Hash Shuffle移除,将Hash shuffle方案移植到Sort Shuffle

在这里插入图片描述

  • 在优化前的Hash shuffle:
    在这里插入图片描述
存在的问题:
	上游(map端)的每个Task会产生与下游Task个数相等的小文件个数。这种情况会导致上游有非常多的小文件。另外,下游(reduce端)来拉取文件的时候,会有大量的网络IO和磁盘IO过程,因为要打开和读取多个小文件。
  • 经过优化后的Hash shuffle
    在这里插入图片描述
变成了由每个Executor进程产生与下游Task个数相等的小文件数。这样可以大量减小小文件的产生,以及降低下游拉取文件时候的网络IO和磁盘IO过程
  • Sort shuffle:
    在这里插入图片描述
Sort Shuffle分成了两种: 普通机制和bypass机制。具体使用哪种,由Spark底层决定。

普通机制的运行过程: 每个上游Task线程处理数据,数据处理完以后,先放在内存中。接着对内存中的数据进行分区、排序。将内存中的数据溢写到磁盘,形成一个个的小文件。溢写完成以后,会将多个小文件合并成一个大的磁盘文件。并且针对每个大的磁盘文件,会提供一个索引文件。接着是下游Task根据索引文件来读取相应的数据。

bypass机制: 就是在普通机制的基础上,省略了排序的过程

bypass机制的触发条件是:
1- 上游RDD的分区数量最多不能超过200个
2- 上游不能对数据进行提前聚合操作(因为提前聚合,需要先进行分组操作,而分组的操作实际上是有排序的操作)

Job调度流程

主要是讨论:在Driver内部,是如何调度任务
在这里插入图片描述
1- Driver进程启动后,底层PY4J创建SparkContext顶级对象。在创建该对象的过程中,还会创建另外两个对象,分别是: DAGScheduler和TaskScheduler
DAGScheduler: DAG调度器。将Job任务形成DAG有向无环图和划分Stage的阶段
TaskScheduler: Task调度器。将Task线程分配给到具体的Executor执行

2- 一个Spark程序遇到一个Action算子就会触发产生一个Job任务。SparkContext将Job任务给到DAG调度器,拿到Job任务后,会将Job任务形成DAG有向无环图和划分Stage的阶段。并且会确定每个Stage阶段有多少个Task线程,会将众多的Task线程放到TaskSet的集合中。DAG调度器将TaskSet集合给到Task调度器

3- Task调度器拿到TaskSet集合以后,将Task分配给到给到具体的Executor执行。底层是基于SchedulerBackend调度队列来实现的。

4- Executor开始执行任务。并且Driver会监控各个Executor的执行状态,直到所有的Executor执行完成,就认为任务运行结束

5- 后续过程和之前一样

Spark RDD 并行度

整个Spark应用中,影响并行度的因素有以下两个原因:

  • 1- 资源的并行度: Executor数量 和 CPU核心数 以及 内存的大小
  • 2- 数据的并行度: Task的线程数 和 分区数量
一般将Task线程数设置为CPU核数的2-3倍。另外每个线程分配3-5GB的内存资源。

如何设置并行度:
在这里插入图片描述

说明: spark.default.parallelism该参数是SparkCore中的参数。该参数只会影响shuffle以后的分区数量。
另外该参数对parallelize并行化本地集合创建的RDD不起作用。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

RBAC权限管理概念

基于RBAC模型的权限设计:如何设计系统权限体系? | 人人都是产品经理 一,什么是RBAC RBAC(基于角色的权限控制)模型的核心是在用户和权限之间引入了角色的概念。取消了用户和权限的直接关联,改为通过用户关联角色、角色关联权限的…

虾皮如何查看自己的店铺

在虾皮(Shopee)平台上查看自己的店铺是非常重要的,因为它可以帮助您了解店铺的运营情况、管理商品和处理客户服务等。下面是在虾皮平台上查看店铺的步骤: 先给大家推荐一款shopee知虾数据运营工具知虾免费体验地址(复制…

nn网络层-卷积层

一、1d/2d/3d Convolution 卷积运算:卷积核在输入信号(图像)上滑动,相应位置上进行乘加卷积核:又称为滤波器,过滤器,可认为是某种模式,某种特征。卷积过程类似于用一个模版去图像上…

【JAVA】怎么确保一个集合不能被修改

🍎个人博客:个人主页 🏆个人专栏: JAVA ⛳️ 功不唐捐,玉汝于成 目录 前言 正文 示例: 不可修改的List: 不可修改的Set: 不可修改的Map: 结语 我的其他博…

强化学习在生成式预训练语言模型中的研究现状简单调研

1. 绪论 本文旨在深入探讨强化学习在生成式预训练语言模型中的应用,特别是在对齐优化、提示词优化和经验记忆增强提示词等方面的具体实践。通过对现有研究的综述,我们将揭示强化学习在提高生成式语言模型性能和人类对话交互的关键作用。虽然这些应用展示…

STM32F103C8T6内部自带Bootloader模式之使用FlyMcu烧写程序

简介 实现自己的Bootloader前, 使用一下STM32内部自带的Bootloader对STM进行烧写 步骤 下载FlyMCU 参考 普中STM32-PZ6806L 使用FlyMcu串口烧录程序 Boot选择 Boot0->1 , Boot1->0 进到系统存储器 打开FlyMCU 1 选择串口波特率 2 选择程序 3 不需要使用辅助引脚 4 开…

Linux网络配置与抓包工具介绍

目录 一、配置命令 1. ifconfig 1.1 概述信息解析 1.2 常用格式 2. ip 2.1 ip link 数据链路层 2.2 ip addr 网络层 2.3 路由 3. hostname 3.1 临时修改主机名 3.2 永久修改主机名 4. route 5. netstat 6. ss 7. ping 8. traceroute 9. nslookup 10. 永久修…

书生·浦语大模型全链路开源体系 学习笔记 第三课

huggingface-cli: command not found 按照该文档解决即可 https://github.com/huggingface/huggingface_hub/issues/1079 具体如下: 1、确保环境已将安装huggingface-cli 2、版本需要旧版,pip install huggingface_hub0.20.1 3、再按如下执行 # T…

WCF几种寄宿方式IIS、Winform、控制台、Windows服务

WCF寄宿方式是一种非常灵活的操作,可以在IIS服务、Windows服务、Winform程序、控制台程序中进行寄宿,从而实现WCF服务的运行,为调用者方便、高效提供服务调用。本文分别对这几种方式进行详细介绍并开发例子进行说明,以求大家对WCF寄宿的方式进行全面的认识和了解。 1、 WC…

计算机毕业设计 基于SpringBoot的项目申报系统的设计与实现 Java实战项目 附源码+文档+视频讲解

博主介绍:✌从事软件开发10年之余,专注于Java技术领域、Python人工智能及数据挖掘、小程序项目开发和Android项目开发等。CSDN、掘金、华为云、InfoQ、阿里云等平台优质作者✌ 🍅文末获取源码联系🍅 👇🏻 精…

探索雷盛537威士忌的魅力:从观色、闻香到品鉴

威士忌,这一源于苏格兰的特别烈酒,以其丰富的味蕾和特别的魅力征服了全球的品鉴者。品鉴威士忌不仅仅是一种感官体验,更是一种探索和发现的旅程。在本文中,我们将以雷盛537威士忌为例,与您深入了解品鉴威士忌的全过程&…

React-Hoc高阶组件与css-in-js技术

Hoc高阶组件 Higher - Order Components:在原有组件基础之上加工后新生成得到的新组件。【高阶组件】 const NewComponent HOC(YourComponent) 通俗的来讲,高阶组件就相当于手机壳,通过包装组件,增强组件功能。 HOC实现步骤&…

三分钟轻松搞懂 HashMap 死循环问题!

三分钟轻松搞懂 HashMap 死循环问题! HashMap 死循环发生在 JDK 1.7 版本中,形成死循环的原因是 HashMap 在 JDK 1.7 使用的是头插法,头插法 链表 多线程并发 HashMap 扩容,这几个点加在一起就形成了 HashMap 的死循环。 前置…

Adding Conditional Control to Text-to-Image Diffusion Models——【代码复现】

官方实现代码地址:lllyasviel/ControlNet: Let us control diffusion models! (github.com) 一、前言 此项目的使用需要显存大于8G,训练自己的ControlNet或需要更大,因此请注意查看自身硬件是否符合。 在此之前请确保已经安装好python以及…

【UE Niagara学习笔记】05 - 喷射火焰顶部的蓝色火焰

在上一篇博客(【UE Niagara学习笔记】04 - 火焰喷射时的黑烟效果)的基础上继续实现在火焰喷射的起点位置生成蓝色火焰的效果。 目录 效果 步骤 1. 创建新的发射器 2. 减少粒子生成数量 3. 减小粒子初始大小 4. 减少粒子喷射距离 5. 减少粒子初始…

在Linux上搭建Maven仓库

目录 一、下载安装包二、安装maven三、修改配置文件settings.xml四、配置环境变量五、测试maven是否可用 一、下载安装包 我在这里为大家准备好了apache-maven-3.5.0-bin.tar.gz,百度网盘下载链接如下: 链接:https://pan.baidu.com/s/1bGun…

python编程使用selenium模拟登陆淘宝实例代码

selenium简介 selenium 是一个web的自动化测试工具,不少学习功能自动化的同学开始首选selenium ,相因为它相比QTP有诸多有点: * 免费,也不用再为破解QTP而大伤脑筋* 小巧,对于不同的语言它只是一个包而已&#xff0c…

AFL进阶教学——插桩、执行、覆盖率收集与反馈(解析)

AFL(American Fuzzy Lop)是一个面向安全的模糊测试工具,它使用编译时插桩技术和遗传算法,可以自动发现触发目标二进程程序的测试用例,从而大大提高测试代码的功能覆盖率。本文主要讲述AFL是如何实现插桩的,…

提升网络安全重要要素IP地址

在数字化时代,网络安全已经成为人们关注的焦点。本文将深入探讨网络安全与IP地址之间的紧密联系,以及IP地址在构建数字世界的前沿堡垒中的关键作用。 网络安全是当今数字社会中不可忽视的挑战之一。而IP地址,作为互联网通信的基础协议&#…

RT-Thread:ADC 框架应用,通过 STM32CubeMX 配置 STM32 ADC驱动

关键词:ADC,RT-Thread ADC,STM32 ADC应用 说明:本笔记是记录如何开启 RT-Thread 框架的ADC功能,使用系统自带的ADC函数,并通过 STM32CubeMX 配置 STM32 ADC驱动 。 1. 打开board.h 文件,找到ADC 使用配置的流程&…