mapreduce_yonghutwo的专栏-程序员宅基地

技术标签: mapreduce  hadoop  

Hadoop mapreduce对外提供了5个可编程组件,分别是InputFormat,Mapper,Partitioner,Reducer,OutputFormat
mapreduce能解决的问题有一个共同特点:任务可被分解成多个子问题,且这些子问题相对独立,彼此不会相互牵制。
分治的思想。
task分为maptask和reducetask。hdfs以固定大小的block为基本的存储单元,而对于mapreduce而言,其处理单位是split,
split是逻辑概念,它包含一些元数据信息,比如数据的起始位置,数据长度,数据所在节点等。它的划分由用户自己决定,
split的多少决定了maptask的数目,因为每个split会交给一个maptask处理。


maptask执行过程(map,buffer,split,sort(partition,key),combiner):先将对应的split迭代解析成一个个key/value对,依次
调用map()函数进行处理,Map的输出是由collector控制的,输出的数据首先被写进
环形内存缓冲区,这个缓冲区默认大小是100M,可以通过io.sort.mb属性来设置具体的大小,当缓冲区中的数据量达到一个特定
的阀值(io.sort.mb * io.sort.spill.percent,其中io.sort.spill.percent 默认是0.80)时,系统将会启动一个后台线程把
缓冲区中的内容spill 到磁盘(Map输出总是写到本地磁盘)。在spill过程中,Map的输出将会继续写入到缓冲区,但如果缓冲区已经满了,Map就会被阻塞
直到spill完成。spill线程在把缓冲区的数据写到磁盘前,会对他进行一个二次排序,首先根据数据所属的partition排序,
然后每个partition中再按Key排序。输出包括一个索引文件和数据文件,如果设定了Combiner,将在排序输出的基础上进行。
Combiner就是一个Mini Reducer,它在执行Map任务的节点本身运行,先对Map的输出作一次简单的Reduce,使得Map的输出更紧凑,
更少的数据会被写入磁盘和传送到Reducer。Spill文件保存在由mapred.local.dir指定的目录中,Map任务结束后删除。
每当内存中的数据达到spill阀值的时候,都会产生一个新的spill文件,所以在Map任务写完他的最后一个输出记录的时候,可能
会有多个spill文件,在Map任务完成前,所有的spill文件将会被归并排序为一个索引文件和数据文件。这是一个多路归并过程,
最大归并路数由io.sort.factor 控制(默认是10)。


reduce执行过程(复制map输出,排序合并,读取<key,value list>进行reduce处理):
Reduce任务的输入数据分布在集群内的多个Map任务的输出中,只要有其中一个Map任务完成,
Reduce任务就开始拷贝他的输出。这个阶段称为复制阶段,Reduce任务拥有多个拷贝线程,可以并行的获取Map输出。可以通过
设定mapred.reduce.parallel.copies来改变线程数。
如果reduce端接受的数据量相当小,则直接存储在ReduceTask内存中
(缓冲区大小由mapred.job.shuffle.input.buffer.percent属性控制,表示用作此用途的堆空间的百分比),
如果数据量超过了该缓冲区大小的一定比例(由mapred.job.shuffle.merge.percent决定),则对数据合并后溢写到磁盘中
或者达到了Map输出的阀值的大小(由mapred.inmem.merge.threshold控制),
在reduce复制map输出的同时,reduce任务就进入了合并排序阶段
缓冲区中的数据将会被归并然后spill到磁盘。拷贝来的数据叠加在磁盘上,有一个后台线程会将它们归并为更大的排序文件,
这样做节省了后期归并的时间。对于经过压缩的Map 输出,系统会自动把它们解压到内存方便对其执行归并。
当所有的Map 输出都被拷贝后,Reduce 任务进入排序阶段(更恰当的说应该是归并阶段,因为排序在Map 端就已经完成),
这个阶段会对所有的Map 输出进行归并排序,这个工作会重复多次才能完成。
JVM重用


•启动JVM是一个比较耗时的工作,所以在MapReduce中有JVM重用的机制。
•条件是统一个作业的任务。
•可以通过mapred.job.reuse.jvm.num.tasks定义重用次数,如果属性是-1那么为无限制。




第三章 Mapreduce编程模型
3.1.1 mapreduce编程接口体系结构
mapreduce编程模型位于应用程序层和mapreduce执行器之间,可分两层,第一层是最基本的Java API,主要有五个可编程组件
InputFormat,Mapper,Partitioner,Reducer,OutputFormat。Hadoop自带了很多可以直接使用的InputFormat,Partitioner,OutputFormat
第二层是工具层,四个工具包JobControl(编写有依赖关系的作业),ChainMapper/ChainReducer(编写链式作业),Hadoop Streaming(脚本),Hadoop Pipes(c/c++编程)
3.1.2 新旧API对比
旧版api在org.apache.hadoop.mapred包中,新版在org.apache.hadoop.mapreduce包及子包中
接口变抽象类,抽象类具有良好的向后兼容性,当需要为抽象类添加新方法时,只要新添加的方法提供了默认实现,用户之前的代码不必修改,
编程组件变抽象类。
3.2.1 序列化
序列化的两个作用:永久存储和进程间通信
Hadoop mapreduce中使对象可序列化的方法是让其对应的类实现Writable接口,对于key需要比较排序,key要实现WritableComparable接口
3.2.3 回调机制
mapreduce对外提供的5个组件,全部属于回调接口。当用户按照约定实现这几个接口后,mapreduce运行时环境会自动调用他们。
3.3.1 Hadoop配置文件和作业配置
后添加的属性取值覆盖掉前面所添加资源中的属性,被final修饰的属性不能被后面定义的属性覆盖
Hadoop默认先加载core-default.xml,hdfs-default.xml和mapred-default.xml,然后加载管理员自定义配置文件core-site.xml,
hdfs-site.xml和mapred-site.xml
3.3.2 InputFormat的设计和实现
InputFormat主要描述输入数据的格式,它提供以下两个功能:数据切分,将输入数据切分为若干个split,以便确定map task数量;
为Mapper提供输入数据,将给定的split解析成一个个key value对
新版API中InputFormat是抽象类,包含两种方法
public abstract List<InputSplit> getSplits(JobContext context) throws IOException, InterruptedException;
public abstract RecordReader<K,V> createRecordReader(InputSplit split, TaskAttemptContext context) throws IOException,InterruptedException;
getSplits()方法在逻辑上对输入数据分片,InputSplit只记录了分片的元数据信息,比如起始位置,长度及所在的节点列表
createRecordReader()方法返回RecordReader对象,该对象可将输入的InputSplit解析成key/value对。map执行过程中会不断调用
RecordReader对象中的方法,迭代获取key/value对交给map函数处理
整个基于文件的InputFormat体系的设计思路是由公共基类FileInputFormat采用统一的方法对各种输入文件进行切分。而由各个派生
InputFormat自己提供机制将进一步解析InputSplit,具体的实现是基类FileInputFormat提供getSplit实现,派生类提供createRecordReader实现
系统自带的各种InputFormat实现。他们都集成自InputFormat,基于数据库的InputFormat实现DBInputFormat,基于文件的InputFormat
实现基类FileInputFormat,并由此派生出TextInputFormat和,KeyValueTextInputFormat,NLInputFormat。针对二进制格式的SequenceFileInputFormat等
FileInputFormat基类的实现,它的重要功能是为各种InputFormat提供统一的getSplit函数,该函数最核心的两个算法是文件切分算法
和host选择算法。
(1)文件切分算法
旧API:
splitSize=max{minSize,min{goalSize,blockSize}}
minSize,InputSplit的最小值,由配置参数mapred.min.split.size确定,默认是1
goalSize,根据totalSize/numSplits,其中totalSize为文件总大小,numSplits为用户设定的Map Task个数,默认是1
blockSize,文件在hdfs中块的大小,默认64M
新API:
splitSize=max(minSize, min(maxSize, blockSize));
-----------------
blockSize = file.getBlockSize();
-----------------
minSize = Math.max(getFormatMinSplitSize(), getMinSplitSize(job));
getFormatMinSplitSize() return 1;
getMinSplitSize(JobContext job) return job.getConfiguration().getLong(SPLIT_MINSIZE, 1L);
SPLIT_MINSIZE = "mapreduce.input.fileinputformat.split.minsize";
-----------------
maxSize = getMaxSplitSize(job);
getMaxSplitSize(JobContext context) return context.getConfiguration().getLong(SPLIT_MAXSIZE,Long.MAX_VALUE);
SPLIT_MAXSIZE = "mapreduce.input.fileinputformat.split.maxsize";


一旦确定splitSize值后,FileInputFormat将文件依次切分成splitSize的InputSplit,最后剩余不足的splitSize的数据块单独成为
一个InputSplit。
(2) host选择算法
待InputSplit切分方案确定后,下一步要确定每个InputSplit的元数据信息。这通常由四部分组成:<file,start,length,hosts>,分别表示
InputSplit所在的文件、起始位置,长度,以及所在的host(节点)列表。在进行任务调度时,优先让空闲资源处理本节点的数据,
如果节点上没有可处理的数据,则处理同一机架上的数据,最差的情况是处理其他机架上的数据。
虽然InputSplit对应的block可能位于多个节点上,但考虑任务调度的效率,通常不会把所有节点加到InputSplit的host列表中,而是选择包含(InputSplit)
数据总量最大的前几个节点(Hadoop限制最多选择10个,多余的会过滤掉),以作为人物调度时判断任务是否具有本地性的主要凭证。为此
FileInputFormat设计了一个简单有效的启发式算法:首先按照rack包含的数据量对rack进行排序,然后在rack内部按照每个node包含的数据量对node排序。
最后取前N个node的host作为InputSplit的host列表,这里的N为block副本数。
host选择算法可知,当InputSplit尺寸大于block尺寸时,map Task并不能实现完全数据本地性,所以当使用基于FileInputFormat时,为提高map task的数据
本地性,尽量使用InputSplit与block大小相同。
派生类实现getRecordReader函数,该函数返回一个RecordReader对象,它实现了类似迭代器的功能,将某个InputSplit解析成
一个个key/value对,在具体实现时RecordReader应考虑以下两点:定位记录边界,为了能够识别一条完整的记录,记录之间应该添加一些同步标识,
对于TextInputFormat,每两条记录之间存在换行符。另外,FileInputFormat对文件的切分是严格按照偏移量来的,因而InputSplit的第一条记录和最后一条记录
可能会被从中间分开,为了解决这种记录跨InputSplit的读取问题,RecordReader规定每个InputSplit的第一条不完整记录划给前一个InputSplit处理。
TextInputFormat关联的是LineRecordReader,对于跨InputSplit的行,LineRecordReader会自动跨InputSplit去读取。
以行记录形式的文本,还真可能存在一行记录被划分到不同的Block,甚至不同的DataNode上去。通过分析FileInputFormat里面的getSplits方法,可以得出,某一行记录同样也可能被划分到不同的InputSplit。
第二点解析key/value,对于TextInputFormat,每一行的内容即为value,而该行在整个文件中的偏移量为key
几个简单的结论:
1. 一个split不会包含零点几或者几点几个Block,一定是包含大于等于1个整数个Block
2. 一个split不会包含两个File的Block,不会跨越File边界
3. split和Block的关系是一对多的关系
4. maptasks的个数最终决定于splits的长度


文件输入
•实现类:FileInputFormat
•通过文件作为输入源的基类。
•四个方法:
•addInputPath()
•addInputPaths()
•setInputPath()
•setInputPaths()
•FileInputFormat会按HDFS块的大小来分割文件
•避免分割
•继承FileInputFormat 重载isSplitable()
•return false
•实现类:TextInputFormat
•TextInputFormat 是默认的输入格式。
•包括:
•KeyValueTextInputFormat
•NLineInputFormat
•XML
•输入分片与HDFS块之间的关系
•TextInputFormat的某一条记录可能跨块存在


二进制输入


•实现类:SequenceFileInputFormat
•处理二进制数据
•包括:
•SequenceFileAsTextInputFormat
•SequenceFileAsBinaryInputFormat


多文件输入


•实现类:MultipleInputs
•处理多种文件输入
•包括:
•addInputPath


数据库输入


•实现类:DBInputFormat
•注意使用,因为连接过多,数据库无法承受。
3.3.3 OutputFormat抽象类设计与实现
OutputFormat主要用于描述输出数据的格式,它能够将用户提供的key/value对写入特定格式的文件中。
OutputFormat抽象类提供了checkOutputSpecs方法在用户提交作业前,检查输出目录是否存在,存在则抛出异常
getRecordWriter方法返回一个RecordWriter对象,该类中的方法write接收一个key/value对,并将其写入文件。
基类FileOutputFormat需要提供所有基于文件的OutputFormat实现的公共功能,主要有以下两个:
(1)实现checkOutputSpecs抽象方法
(2)处理side-effect file,任务的side-effect file并不是任务的最终输出文件,而是具有特殊用途的任务专属文件,
它的典型应用是推测式任务,在hadoop中,同一作业的某些任务可能慢于其他任务,这种任务会拖慢整个作业的执行速度,Hadoop会在另一个节点上启动一个相同的
任务,该任务便被称为推测式任务,为防止这两个任务同时往输出文件中写入数据发生冲突,FileOutputFormat会为每个task的数据创建一个side-effect file,并将
产生的数据临时写入该文件,待task结束后,再移动到最终输出目录。这些文件的创建,删除,移动等均由OutputCommitter完成。它是一个抽象类,FileOutputCommitter
继承自OutputCommitter,并重写相关方法。用户可以编写自己的OutputCommitter,并通过参数mapred.output.committer.class指定
MultipleOutputs合并了旧版本的MultipleOutputs功能和MultipleOutputFormat功能,新api都是用mapreduce包。
用法:在setup中new MultipleOutputs 对象,mapreduce中mos.write,cleanup中close()。
public <K, V> void write(String namedOutput, K key, V value)
      throws IOException, InterruptedException


public <K, V> void write(String namedOutput, K key, V value,
      String baseOutputPath) throws IOException, InterruptedException 


public void write(KEYOUT key, VALUEOUT value, String baseOutputPath) 
      throws IOException, InterruptedException 


LazyOutputFormat.setOutputFormatClass(job,
                TextOutputFormat.class);


3.3.4 Mapper与Reducer解析
mapreduce提供了很多Mapper/Reducer实现:
ChainMapper/ChainReducer:用于支持链式作业
IdentityMapper/IdentityReducer:对于key/value不进行任何处理直接输出
InvertMapper:交换key/value位置
RegexMapper:正则表达式字符串匹配
TokenMapper:将字符串分割成若干个token(单词),可做WordCount的Mapper
LongSumReducer:以key为组,对long类型的value求累加和
Mapper包括初始化setup,map操作(mapreduce框架会通过InputFormat的RecordReader从InputSplit获取一个个keyvalue对,交给map函数处理)和清理cleanup三部分
新版API和旧版API区别:Mapper由接口变为抽象类,且不再继承jobConfiguration和Closeable两个接口,而是直接添加setup和cleanup两个方法
将参数封装到Context对象中
去掉MapperRunnable接口,在Mapper中添加run方法,以方便用户定制map()函数的调用方法,实现与原来一致。
对于一个Mapreduce应用程序,不一定非要存在Mapper。mapreduce提供了run方法,用户可以重写该方法自己实现处理逻辑


3.3.5 Partitioner抽象类的设计与实现
Partitioner的作用是对Mapper产生的中间结果进行分片,以便将同一分组的数据交给同一个Reduce处理,他直接影响Reduce阶段的负载均衡
包含一个抽象方法getPartition(KEY key, VALUE value, int numPartitions),numPartitions指reduce的个数,
mapreduce提供了两个Partitioner实现HashPartitioner和TotalOrderPartitioner,HashPartitioner是默认实现,它是基于hash值得分片
方式(key.hashCode() & Integer.MAX_VALUE) % numReduceTasks。
TotalOrderPartitioner提供了一种基于区间的分片方法,它能够按照大小将数据分成若干个区间,保证后一个区间的所有数据均大于
前一个区间的数据。(首先数据采样后根据reduce task数量获得分割点(Hadoop自带很多采样算法IntercalSampler,RandomSampler,SplitSampler),
,然后map阶段,将分割点保存到trie树中,以便于快速定位查找,最后reduce阶段,每个reduce对分配的区间数据进行局部排序,最终得到全排序数据)
基于TotalOrderPartitioner全排序的效率跟key分布规律和采样算法有直接关系,key值分布越均匀且采样越具有代表性,则reduce task负载
越均衡,全排序效率越高。
TotalOrderPartitioner有两个典型的应用实例:TeraSort和Hbase批量数据导入
Hadoop中TeraSort算法分析http://dongxicheng.org/mapreduce/hadoop-terasort-analyse/
Hbase以resion为单位划分数据,resion有序,resion内部数据有序(按key排列)
3.4.1 Hadoop Streaming的实现原理
Hadoop Streaming允许用户将任何可执行文件或脚本作为Mapper/Reducer,Hadoop Streaming要求用户编写的Mapper和Reducer
从标准输入中读取数据,并将结果写到标准数据中,类似以Linux的管道。
提交作业的命令:hadoop jar hadoop-streaming.jar -file myScript -input myInputDirs -output myOutputDirs -mapper Myscript -reducer /bin/wc
-file 可以使可执行文件成为作业的一部分,并且会一起打包提交
实现Hadoop Streaming的技术关键点是如何使用标准输入输出实现java与可执行文件或脚本文件之间的通信,为此Hadoop Streaming使用了JDK中的
java.lang.ProcessBuilder类,该类提供了一整套管理操作系统进程的方法,包括创建、启动和停止进程等。
3.4.2 Hadoop Pipes实现原理
Hadoop Pipes是hadoop方便c/c++用户编写mapreduce程序而设计的工具。其设计思想是将应用逻辑相关的C++代码放到单独进程中,然后通过
Socket让java代码与c++代码通信完成数据计算。
Hadoop Streaming与Hadoop Pipes的不同之处是hadoop streaming 采用标准输入输出,而Hadoop Pipes采用Socket
3.5.1 JobControl的实现原理
用户只需要使用job.addDepending()函数添加作业依赖关系接口,jobControl会按照依赖关系调度各个作业
//创建configuration对象,配置configuration
//创建job
//设置依赖关系
//创建jobControl对象,jobControl.addJob(job),jobControl.run()
jobControl由两个类组成jobControl和job,job封装了一个mapreduce作业及其对应的依赖关系,主要负责监控各个依赖作业的运行状态
以此更新自己的状态(WAITING,REDAY,RUNNING,SUCCESS,FALDED),如果一个作业的依赖作业失败,则该作业也失败。
jobControl封装了一系列mapreduce作业及其对应的依赖关系,它将处于不同状态的作业放入不同的hash表中,按照job的状态转移作业,直到所有作业完成
在实现的时候,jobControl包含一个线程用于周期性的监控和更新各个作业的运行状态,调度依赖作业运行完成的作业,提交处于ready状态的作业。
3.5.2 ChainMapper/ChainReducer的实现原理
ChainMapper和ChainReducer主要为了解决线性链式Mapper提出的,也就是说在map或者reduce阶段存在多个Mapper,这些Mapper像Linux管道一样,
前一个Mapper的输出结果直接重定向到下一个Mapper的输入,形成一个流水线,形式类似于[MAP+,REDUCE,MAP*]。注意对于任意一个mapreduce作业,
map和reduce阶段可以有无限个map,但reduce只能有一个。
3.5.3 Hadoop工作流引擎
Hadoop之上出现了很多开源的工作流引擎,主要概括为两类:隐式工作流引擎和显式工作流引擎。
隐式工作流引擎在mapreduce之上添加了一个语言抽象层,允许用户使用更简单的方式编写应用程序,如hive和pig
显式工作流引擎直接面向mapreduce应用程序开发,提供了一种作业依赖关系描述,并按照这种方式进行作业调度,典型代表如oozie(采用xml)






map reduce 个数
调度器


mapreduce压缩
但可以很简单的设置mapred.compress.map.output为true 启用该功能。
压缩所使用的库由mapred.map.output.compression.codec来设定
mapred.output.compress=true
mapred.output.compression.codec=org.apache.Hadoop.io.compress.GzipCode
Using Compression in MapReduce
MapReduce读取输入路径中的压缩文件时会自动完成数据解压(可参考CompressionCodecFactory)。
如果MapReduce Job的结果输出需要使用压缩,可以通过设置Job的相关配置属性来实现:
mapreduce.output.fileoutputformat.compress:true
mapreduce.output.fileoutputformat.compress.codec:CompressionCodec全限定类名eg:org.apache.Hadoop.io.compress.GzipCode
也可以通过FileOutputFormat提供的静态方法设置,如:
FileOutputFormat.setCompressOutput(job, true);
FileOutputFormat.setOutputCompressorClass(job, GzipCodec.class);
不同的输出文件格式可能相应的设置属性会有不同。
Compressing map output
Map Task的输出被写出到本地磁盘,而且需要通过网络传输至Reduce Task的节点,只要简单地使用一个快速的压缩算法(如LZO、LZ4、Snappy)就可以带来性能的提升,因为压缩机制的使用避免了Map Tasks与Reduce Tasks之间大量中间结果数据被传输。可以通过设置相应的Job配置属性开启:
mapreduce.map.output.compress:true
mapreduce.map.output.compress.codec:CompressionCodec全限定类名
也可以通过Configuration API进行设置:
new API:
Configuration conf = new Configuration();
conf.setBoolean(Job.MAP_OUTPUT_COMPRESS, true);
conf.setClass(Job.MAP_OUTPUT_COMPRESS_CODEC, GzipCodec.class, CompressionCodec.class);
Job job = new Job(conf);


old API:
conf.setCompressMapOutput(true);
conf.setMapOutputCompressorClass(GzipCodec.class);
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/yonghutwo/article/details/51828545

智能推荐

int linux 原子操作_Linux下的原子操作_华雯婷的博客-程序员宅基地

linux支持的哪些操作是具有原子特性的?知道这些东西是理解和设计无锁化编程算法的基础。__sync_fetch_and_add系列的命令,发现这个系列命令讲的最好的一篇文章,英文好的同学可以直接去看原文。Multithreaded simple data type access and atomic variables__sync_fetch_and_add系列一共有十二个函数,有加/减/与/或...

layer.js 下easyui datetimebox 不能用的问题_能否在遇见的博客-程序员宅基地

问题:今天写页面时,编辑页面为layer.js插件弹出框。里面用到了easyui的datetimebox,发现datatimebox点击没反应问题分析:后来发现时z-index的问题。layer.js弹出框默认的z-index为19891014,比一般的都大,所以会覆盖datetimbox的弹出框解决:设定layer弹出框的z-index,修改小点儿即可。例如:    ...

Linux添加PCF8563 RTC支持_宁静致远2021的博客-程序员宅基地_linux pcf8563驱动

文章目录1. 添加驱动支持2. 添加设备树3. 测试原文链接:https://blog.csdn.net/WXXGoodJob/article/details/88692949SOC:RK3288kernel:Linux4.11. 添加驱动支持Device Drivers ---&gt; [*] Real Time Clock ---&gt; [*] Set system time from RTC on startup and resume

分享 十个日常使用的脚本,你会了吗?_网站开发建设专家的博客-程序员宅基地_电脑脚本

作为程序员,每天都很多问题需要编码来解决,有些问题仅通过 Python 的标准库并不能轻松解决,本文今天分享一些高频问题的解决方案,可以作为一个手边的工具箱,你可以先收藏备用。1、测网速,选择最佳服务器这个脚本可以测试上传、下载速度,也提供了函数 get_best_server 来选择最佳服务器,在客户端和多服务器模式中非常实用。脚本:#pipinstallpyspeedtest#pipinstallspeedtest#pipinstallspeedtest-cli...

H3C客户端常见问题解决_weixin_34177064的博客-程序员宅基地

常见问题及解决方法:1、端口、IP地址、MAC地址绑定失败?原因:A、用户更改了IP地址,或更换新网卡。B、用户换了机器,或在他人机器上用自已的用户登陆C、用户主机连交换机的端口改变 解决办法:身份验证系统己对三者实施绑定,请用户持×××至网络中心解决。2、认证通过,网络状态显示已经连接,但只能发送数据包而不能接收,不能上网?原因:A、IP地址设置有误:有的用户IP地址和他人...

矩阵快速幂优化dp__kikyou-的博客-程序员宅基地_矩阵快速幂优化dp

文章目录构造矩阵快速幂优化线性递推式POJ3734[Buses Gym - 101473H](https://vjudge.net/problem/Gym-101473H)[CF222E Decoding Genome](https://codeforces.com/problemset/problem/222/E)构造矩阵快速幂优化线性递推式遇到某些线性递推式,我们可以设法构造成矩阵乘积的形式,像斐波那契数列 f[i]=f[i-1]+f[i-2] ,写成矩阵乘积的好处就是,由于矩阵乘积具有结合

随便推点

卫春芳计算机基础视频,第一章 计算机基础知识.pptx_ynjkl007的博客-程序员宅基地

文档介绍:大学计算机基础主讲:数计学院卫春芳所用教材:《大学计算机基础》科学出版社大学计算机基础高等教育出版社杨振山龚沛曾主编大学计算机基础(第4版)大学计算机基础实验教程(电子版)参考书目湖北大学→图书馆→馆藏资源→电子图书→中文数据库→超星电子图书→超星图书库→输入书名→搜索作者: 徐进华,钱毅湘等出版日期: 2011.632授课+32上机重点讲授计算机的基本原理、基本知识、基本方法,注...

DOS运行GHOST加参数_舞夜狂飙的博客-程序员宅基地

Ghost是一个典型的支持参数的DOS程序,充分利用它的参数,我们可以更好地控制Ghost。让它们更好地为我们工作,前面几个例子,我们就使用了Ghost的参数做出了一张自动备份和恢复硬盘数据的自启动光盘。正是因为Ghost参数众多,功能强大,我们才有必要把一些最最常用的参数列出,供大家平时参考使用。  提示:  (1)参数(Parameter)是程序提供给我们一些隐藏选项,通过添加

单行、多行输入框,其属性及功能场景_诗不姓的博客-程序员宅基地_android输入框单行

---单行输入框editText1.setSingleLine();editText1.setEms(10);editText1.setFilters(new InputFilter[] { new InputFilter.LengthFilter(5) });

人人都在讨论图数据库,它到底好在哪——创邻科技_创邻科技的博客-程序员宅基地_图数据库优缺点

人人都在讨论图数据库,它到底好在哪?【摘要】图数据库不是存储图片的数据库,而是存储顶点与他们之间关系的数据库。与传统关系型数据库相比,图数据库的优势体现在直观性、灵活性、高性能等方面。图数据库支持多种图算法,可以应用于社交网络、金融欺诈检测、实时推荐引擎、知识图谱、网络/IT运营等多个领域。随着近年来云计算、大数据、物联网等技术产业的快速发展,图数据库的使用率不断攀升,一些行业人士称图数据库是增长速度最快的数据库类型。如果说的是事实的话,那么我们了解它是非常有必要的。人们广泛提及的图数据库到底是什

iOS 【语音合成的集成和使用几点建议】_王中尧的博客-程序员宅基地

本文重点介绍在 iOS app 中集成智能语音合成时应该如何在众多只能语音提供商之间选择,另外介绍了在集成科大讯飞语音包的同时官方文档没有提及的一个 bug 的解决方案。

ios真机抓包命令rvictl_想北飞的雁的博客-程序员宅基地_rvictl

转自:http://danqingdani.blog.163.com/blog/static/18609419520135204934551/总的来说,有以下三种方法:一、在PC上设置网络共享,生成wifi热点供移动设备使用二、开启http代理工具服务器(例如burpsuite,charles),然后移动设备通过该HTTP代理上网(只能抓取HTTP/HT

推荐文章

热门文章

相关标签