天道酬勤,学无止境

@parallel和pmap到底有什么区别?(What exactly is the difference between @parallel and pmap?)

问题

如标题所述: @parallelpmap到底有什么区别? 我不是说明显的一个宏是一个循环,另一个是在函数上工作,我的意思是它们的实现有什么确切的区别,我该如何利用这些知识在它们之间进行选择?

我问的原因是,我编写的许多应用程序都可以使用以下一种结构:我可以编写一个循环并使用@parallel计算某些@parallel ,或者将循环中的内容包装到函数中并在其上调用pmap 。 我一直遵循以下建议:使用@parallel进行快速评估的事情,使用pmap进行调用,每个任务花费更长的时间(如文档中所述),但是我觉得如果我对它的工作有了更好的了解我可以做出更好的选择。

例如: @parallel在评估之前将工作分开? 我注意到,如果我运行一个并行循环,其中每个内部调用花费随机的时间, @parallel可能要花费很长时间,因为最后我仍然只有很少的进程在工作。 在相同的微测试上的pmap似乎没有: pmap根据需要重新分配工作?

诸如此类的其他问题都源于我对pmap@parallel到底有何不同的@parallel

回答1

@parallel需要做的工作,divy起来可用的工人当中的时候了。 注意,在?@parallel我们得到The specified range is partitioned ... across all workers. 相比之下, pmap将使每个工作人员开始工作。 工人完成一项工作后,将为它提供下一个可用的工作。 例如,它类似于python中常见的基于队列的多处理。 因此,与其说是“重新分配”工作,不如说是在适当的时候,首先将其分发给适当的工人。

我制作了以下示例,我相信可以说明这一点。 在这个有点愚蠢的示例中,我们有两个工作人员,其中一个很慢,而另一个则快一倍。 理想情况下,我们希望为快工提供的工作量是慢工的两倍。 (或更实际的说,我们将有快速和慢速的工作,但是本金是完全相同的)。 pmap将完成此操作,但@parallel不会。

对于每个测试,我都会初始化以下内容:

addprocs(2)

@everywhere begin
    function parallel_func(idx)
        workernum = myid() - 1 
        sleep(workernum)
        println("job $idx")
    end
end

现在,对于@parallel测试,我运行以下命令:

@parallel for idx = 1:12
    parallel_func(idx)
end

并返回打印输出:

julia>  From worker 2:  job 1
    From worker 3:  job 7
    From worker 2:  job 2
    From worker 2:  job 3
    From worker 3:  job 8
    From worker 2:  job 4
    From worker 2:  job 5
    From worker 3:  job 9
    From worker 2:  job 6
    From worker 3:  job 10
    From worker 3:  job 11
    From worker 3:  job 12

几乎是甜蜜的。 工人们平均地“分担”了工作。 请注意,即使工人2的速度是工人3的两倍,每个工人也完成了6个工作。虽然可能会接触,但是效率低下。

对于pmap测试,我运行以下命令:

pmap(parallel_func, 1:12)

并获得输出:

From worker 2:  job 1
From worker 3:  job 2
From worker 2:  job 3
From worker 2:  job 5
From worker 3:  job 4
From worker 2:  job 6
From worker 2:  job 8
From worker 3:  job 7
From worker 2:  job 9
From worker 2:  job 11
From worker 3:  job 10
From worker 2:  job 12

现在,请注意工人2完成了8个工作,工人3完成了4个工作。这正好与他们的速度成正比,也是我们想要获得最佳效率的目标。 pmap是一个艰巨的任务大师-根据每个人的能力而定。

因此,Julia文档中的建议是有意义的。 如果您有简单的小工作,则@parallel这些问题很可能不会引起问题。 对于更大或更复杂的工作, pmap具有优势。

受限制的 HTML

  • 允许的HTML标签:<a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • 自动断行和分段。
  • 网页和电子邮件地址自动转换为链接。

相关推荐
  • What exactly is the difference between @parallel and pmap?
    As the title states: what exactly is the difference between @parallel and pmap? I don't mean the obvious one's a macro for a loop and the other works on functions, I mean how exactly does their implementation differ and how should I use this knowledge to choose between them? The reason I ask is that a lot of the applications I write could use either construct: I could write a loop and calculate something with @parallel, or wrap what would have been in the loop into a function and call pmap on that. I have been following the advice of using @parallel for things which are quick to evaluate and
  • 初级索引和次级索引之间到底有什么区别? [复制](What is difference between primary index and secondary index exactly? [duplicate])
    问题 这个问题已经在这里有了答案: MySQL中INDEX,PRIMARY,UNIQUE,FULLTEXT之间的区别? (3个答案) 7年前关闭。 谁能告诉我主要索引和次要索引之间的确切区别是什么? 一级和二级索引类别下有哪些不同的索引? 与使用二级索引相比,使用一级索引有什么优势,反之亦然? 回答1 主要指标: 主索引是一组字段的索引,其中包括该字段的唯一主键,并且保证不包含重复项。 也称为聚集索引。 例如。 员工ID可以是它的示例。 次要指标: 次要索引是不是主索引的索引,并且可能有重复项。 例如。 员工姓名可以是它的示例。 因为员工名称可以具有相似的值。 主索引包含表的关键字段。 激活表后,将在数据库中自动创建主索引。 如果经常访问大表而无法应用主索引排序,则应为该表创建辅助索引。 表上的索引具有三个字符的索引ID。 '0'为主索引保留。 客户可以在SAP表上创建自己的索引; 其ID必须以Y或Z开头。
  • C和C ++中的“按引用传递”之间到底有什么区别?(What exactly is the difference between “pass by reference” in C and in C++?)
    问题 C和C ++开发人员都使用短语“通过引用传递”,但是它们似乎用来表示不同的含义。 每种语言中这个模棱两可的词组之间到底有什么区别? 回答1 有些问题已经解决了按引用传递和按值传递之间的区别。 从本质上讲,按值将参数传递给函数意味着函数将拥有其自己的参数副本-将其值复制。 修改该副本不会修改原始对象。 然而,通过引用传递时,在该函数内的参数是指在通过了相同的对象-的任何改变内部的功能可以看到外面。 不幸的是,有两种使用短语“按值传递”和“按引用传递”的方法,这可能会引起混淆。 我认为,这部分是为什么新C ++程序员难以采用指针和引用的原因,尤其是当它们来自C的背景时。 C 在C语言中,技术意义上的一切都是通过价值传递的。 也就是说,无论您将什么作为函数的参数,它都将被复制到该函数中。 例如,调用一个函数void foo(int)与foo(x)副本的值x作为参数foo 。 可以在一个简单的示例中看到: void foo(int param) { param++; } int main() { int x = 5; foo(x); printf("%d\n",x); // x == 5 } x的值被复制到foo并且该副本递增。 main的x继续具有其原始值。 如您所知,对象可以是指针类型。 例如, int* p定义p作为指针以一个int 。 重要的是要注意,以下代码引入了两个对象:
  • DStream和地图中的Spark转换之间有什么确切区别?(what is exact difference between Spark Transform in DStream and map.?)
    问题 我正在尝试了解Spark Streaming中Spark DStream的转换。 我知道与map相比,transform是最高级的,但是有人可以给我一些实时示例或清晰的示例,以区分转换和map吗? 回答1 Spark流中的transform功能允许在流的基础RDDs上使用Apache Spark的任何转换。 map用于元素到元素的转换,可以使用transform实现。 本质上, map在DStream的元素上DStream并且transform允许您使用RDDs的RDD。 您可能会发现http://spark.apache.org/docs/latest/streaming-programming-guide.html#transformations-on-dstreams非常有用。 回答2 map是基本变换,而transform是RDD变换 地图 map(func):通过将源DStream的每个元素传递给函数func来返回新的DStream。 这是一个示例,演示了DStream上的映射操作和转换操作 val conf = new SparkConf().setMaster("local[*]").setAppName("StreamingTransformExample") val ssc = new StreamingContext(conf, Seconds(5))
  • map和flatMap有什么区别,并且每个都有一个很好的用例?(What is the difference between map and flatMap and a good use case for each?)
    问题 有人可以向我解释map和flatMap之间的区别,以及每种情况的好用例是什么? “整理结果”是什么意思? 到底有什么好处呢? 回答1 这是一个区别示例,作为“ spark-shell会话: 首先,一些数据-两行文本: val rdd = sc.parallelize(Seq("Roses are red", "Violets are blue")) // lines rdd.collect res0: Array[String] = Array("Roses are red", "Violets are blue") 现在, map将长度为N的RDD转换为长度为N的另一个RDD。 例如,它从两条线映射到两条线长: rdd.map(_.length).collect res1: Array[Int] = Array(13, 16) 但是flatMap (松散地说)将长度为N的RDD转换为N个集合的集合,然后将它们展平为单个RDD结果。 rdd.flatMap(_.split(" ")).collect res2: Array[String] = Array("Roses", "are", "red", "Violets", "are", "blue") 每行有多个单词,多行,但最终得到一个单词输出数组 只是为了说明这一点,从行集合到单词集合的flatMapping看起来像: [
  • spark.sql.shuffle.partitions和spark.default.parallelism有什么区别?(What is the difference between spark.sql.shuffle.partitions and spark.default.parallelism?)
    问题 spark.sql.shuffle.partitions和spark.default.parallelism什么spark.default.parallelism ? 我试图在SparkSQL设置它们SparkSQL ,但是第二阶段的任务编号始终为200。 回答1 从这里的答案中, spark.sql.shuffle.partitions配置在对联接或聚集的数据进行spark.sql.shuffle.partitions时使用的分区数。 spark.default.parallelism是用户未明确设置的转换(如join , reduceByKey和parallelize返回的RDD中分区的默认数量。 请注意, spark.default.parallelism似乎仅适用于原始RDD并且在处理数据帧时将被忽略。 如果您正在执行的任务不是联接或聚合,而您正在使用数据框,则设置这些将不会有任何效果。 但是,您可以在代码中调用df.repartition(numOfPartitions) (不要忘记将其分配给新的val )来自行设置分区数。 要更改代码中的设置,您只需执行以下操作: sqlContext.setConf("spark.sql.shuffle.partitions", "300") sqlContext.setConf("spark.default
  • spark checkpoint和持久保存到磁盘之间有什么区别(What is the difference between spark checkpoint and persist to a disk)
    问题 spark checkpoint和持久保存到磁盘之间有什么区别。 这些都存储在本地磁盘中吗? 回答1 几乎没有什么重要的区别,但最根本的区别是沿袭会发生什么。 Persist / cache可保持血统不变,而checkpoint则可中断血统。 让我们考虑以下示例: import org.apache.spark.storage.StorageLevel val rdd = sc.parallelize(1 to 10).map(x => (x % 3, 1)).reduceByKey(_ + _) cache / persist : val indCache = rdd.mapValues(_ > 4) indCache.persist(StorageLevel.DISK_ONLY) indCache.toDebugString // (8) MapPartitionsRDD[13] at mapValues at <console>:24 [Disk Serialized 1x Replicated] // | ShuffledRDD[3] at reduceByKey at <console>:21 [Disk Serialized 1x Replicated] // +-(8) MapPartitionsRDD[2] at map at <console>:21
  • 任务和线程有什么区别?(What is the difference between task and thread?)
    问题 在C#4.0中,我们在System.Threading.Tasks命名空间中具有Task 。 Thread和Task之间的真正区别是什么? 为了我自己的学习,我做了一些示例程序(来自MSDN的帮助) Parallel.Invoke Parallel.For Parallel.ForEach 但是有很多疑问,因为这个想法不太清楚。 我最初在Stackoverflow中搜索了类似类型的问题,但可能与此问题标题有关,我无法获得相同的问题。 如果有人知道先前在此处发布的相同类型的问题,请提供链接的参考。 回答1 一项任务是您想要完成的事情。 线程是执行该任务的许多可能的工作程序之一。 用.NET 4.0术语来说,任务表示异步操作。 线程用于通过将工作分解成多个块并分配给单独的线程来完成该操作。 回答2 用计算机科学的术语来说, Task是未来或承诺。 (有些人是这两个术语的同义词,有些人以不同的方式使用它们,没有人可以就一个精确的定义达成一致。)基本上, Task<T> “承诺”给您返回T ,但现在还不是,亲爱的,我有点忙,您为什么以后不回来? Thread是兑现承诺的一种方式。 但是,并非每个Task需要一个全新的Thread 。 (实际上,创建线程通常是不可取的,因为这样做比重用线程池中的现有线程要昂贵得多。稍后会更多。)如果您要等待的值来自文件系统或数据库或网络
  • What is the difference between concurrent programming and parallel programming?(What is the difference between concurrent programming and parallel programming?)
    问题 并发编程和并行编程有什么区别? 我问谷歌,但没有找到任何可以帮助我理解这种差异的东西。 你能给我两个例子吗? 现在,我找到了以下解释:http://www.linux-mag.com/id/7411-但是“并发是程序的属性”与“并行执行是机器的属性”对我来说还不够-我还是不能说什么。 回答1 如果您正在使用线程编程(并行编程),则不一定要这样执行(并行执行),因为这取决于计算机是否可以处理多个线程。 这是一个视觉示例。 非线程机器上的线程: -- -- -- / \ >---- -- -- -- -- ---->> 线程计算机上的线程: ------ / \ >-------------->> 破折号代表执行的代码。 如您所见,它们既可以拆分又可以分别执行,但是线程机可以一次执行多个单独的部分。 回答2 并发编程考虑的操作似乎是重叠的,并且主要与由于不确定性控制流而引起的复杂性有关。 与并发程序相关的定量成本通常既是吞吐量又是等待时间。 并发程序通常受IO约束,但并不总是如此,例如,并发垃圾收集器完全在CPU上。 并发程序的教学示例是Web搜寻器。 该程序启动对网页的请求,并在下载结果可用时并发接受响应,从而累积一组已被访问的页面。 控制流是不确定的,因为每次运行程序时不一定都以相同的顺序接收响应。 这种特性会使调试并发程序变得非常困难。 某些应用程序基本上是并发的,例如
  • 试图找到泄漏! anon对pmap意味着什么?(Trying to locate a leak! What does anon mean for pmap?)
    问题 我试图找到我的内存在Linux上运行的Java进程的去向。 有人建议我使用pmap -x来确切查看内存在做什么。 输出的确很长,但基本上占了很大一部分,它是重复的: 00007fbf75f6a000 1016 - - - rwx-- [ anon ] 00007fbf76068000 12 - - - ----- [ anon ] 这到底是什么意思? 为什么我有这么多条目(4000+)? 回答1 Anon块是通过malloc或mmap分配的“大”块-请参见手册页。 因此,它们与Java堆无关(除了整个堆应该存储在这样的块中的事实)。 以我的经验,线程堆栈也使用匿名块。 如果您看到很多匿名块都具有相同的大小,并且大小为512k至4Mb(对于正在运行的Tomcat进程,以下示例重复了十几次),则可能是原因。 根据程序的不同,您最多可以有几十个。 如果看到成千上万,则表示线程问题。 b089f000 504K rwx-- [ anon ] b091d000 12K ----- [ anon ] b0920000 504K rwx-- [ anon ] b099e000 12K ----- [ anon ] b09a1000 504K rwx-- [ anon ] b0a1f000 12K ----- [ anon ] 但这留下了一个问题:您为什么要使用pmap诊断Java内存问题?
  • .exp的用途是什么,.lib和.dll有什么区别?(What is the use of .exp and what is the difference between .lib and .dll?)
    问题 在编译和链接期间,.exp的用途是什么? .lib和.dll有什么区别? 我知道将使用.lib,而在运行程序时将使用链接和.dll。 但是.lib和.dll到底有什么区别? .lib文件是否不包含来自.dll文件的功能代码? 使用两个单独的文件有什么需要? 请说清楚。 回答1 对于DLL的导入库,.lib文件根本不包含任何实际代码。 它基本上只包含相关DLL中功能的列表-足以使链接程序将对该DLL的引用嵌入与该库链接的内容中,但没有太多其他功能。 .exp文件是导出文件-基本上与.lib文件相同。 有循环依赖关系时(至少主要是)使用它。 例如,假设您有一个DLL充当可执行文件的插件。 该可执行文件提供了一些导出的函数供插件DLL使用,但是还需要能够调用插件中的某些函数(例如,加载和初始化插件)。 直到可执行文件被构建为提供.lib文件后,DLL才会链接-但是,直到将DLL构建为提供.lib文件时,可执行文件才会链接。 要打破依赖关系,请对可执行文件运行链接器,该链接器将失败(因为它找不到DLL的.lib文件),但会生成一个.exp文件。 然后,您将DLL链接到可执行文件的.exp文件。 然后,您可以使用DLL的.lib文件重新运行链接以生成可执行文件。
  • async.series和async.parallel之间的区别(difference between async.series and async.parallel)
    问题 async.series和async.parallel有什么区别。 考虑下面的例子,我得到了相同的结果。 async.parallel([ function(callback){ setTimeout(function(){ callback(null, 'one'); }, 200); }, function(callback){ setTimeout(function(){ callback(null, 'two'); }, 100); }, function(callback){ setTimeout(function(){ var err = new Error('I am the error'); callback(err); }, 400); }, function(callback){ setTimeout(function(){ callback(null, 'three'); }, 600); }, ], // optional callback function(err, results){ if(err){ console.log('Error'); } else { } console.log(results); //results is now equal to [ 'one', 'two', undefined ] // the second
  • JEE和J2EE有什么区别? [复制](What is the difference between JEE and J2EE? [duplicate])
    问题 这个问题已经在这里有了答案: 为什么J2EE名称中第二个? [重复] (1个答案) 4年前关闭。 我想了解JEE和J2EE之间的区别。 我猜这两者都是Java Enterprise开发工具或环境。 但是,是什么使它们完全不同和相似呢? 回答1 首字母缩写词JEE实际上实际上是一个不当使用的名称,不建议使用它。 引用“ Java EE平台规范”页面: 没有什么叫JEE! 切勿使用该名称! 正确的简称是“ Java EE” 首次引入企业Java平台时,它被称为“ Java 2 Platform,Enterprise Edition”,缩写为“ J2EE”。 当我们修改Java平台的命名时,我们不仅删除了“ 2”。 我们更改平台名称的主要原因之一是因为我们想强调它们都是“ Java”。 “ J2EE”,“ J2SE”和“ J2ME”的旧名称没有做到这一点。Java对我们很重要。Java是我们在这里的原因。Java是我们共享的价值。通过谈论“ Java EE”来了解世界。 请仅使用正确的名称“ Java EE”。 如果说或输入的内容太多,则将其称为“ EE”。 (不,不是“ double E”。) 相关问题: 什么是Java EE? Java EE到底是什么? 所有Java EE规范的摘要 堆栈溢出以外的相关内容: Java EE概览 Java EE 7规范API
  • 变量,对象和引用之间有什么区别? [复制](What is the difference between a variable, object, and reference? [duplicate])
    问题 这个问题已经在这里有了答案: 什么是类,引用和对象? (11个答案) 4年前关闭。 变量,对象和引用之间到底有什么区别? 例如:它们都指向某种类型,并且它们都必须都具有值(除非您拥有临时的可为空的类型),但是它们的功能和实现到底有何不同? 例子: Dog myDog = new Dog(); //variable myDog that holds a reference to object Dog int x = 12; //variable x that hold a value of 12 它们具有相同的概念,但是有何不同? 回答1 (请清楚地说,我在这里给出的解释是特定于Java和C#的。尽管可能有些位,但不要假定它适用于其他语言。) 我喜欢用比喻告诉别人我住的地方。 我可以在一张纸上写我的地址: 变量就像一张纸。 它拥有一个价值,但它本身并不是价值。 您可以删除所有内容,然后写其他内容。 我写在纸上的地址就像参考。 这不是我的房子,但这是导航到我的房子的一种方式。 我的房子本身就像一个物体。 我可以给出对同一对象的多个引用,但是只有一个对象。 有帮助吗? 值类型和引用类型之间的区别是写在纸上的内容。 例如,在这里: int x = 12; 就像直接在纸上写上数字12一样。 然而: Dog myDog = new Dog(); 不会将Dog对象的内容本身写在纸上
  • Java实例到底是什么?(What exactly is an instance in Java?)
    问题 对象,实例和引用之间有什么区别? 他们说他们必须为其应用程序创建一个实例吗? 这意味着什么? 回答1 一个对象和一个实例是同一回事。 就个人而言,我更喜欢在指代特定类型的特定对象(例如“ Foo类型的实例”)时使用“实例”一词。 但是,通常在谈论对象时,我会说“对象”而不是“实例”。 引用要么引用特定的对象,要么可以是空引用。 他们说他们必须为其应用程序创建一个实例。 这是什么意思? 它们可能意味着您必须编写如下内容: Foo foo = new Foo(); 如果不确定应实例化的类型,则应联系应用程序的开发人员,并索取更完整的示例。 回答2 “应用程序实例”没有任何意义。 “对象”和“实例”是同一件事。 有一个“类”,用于定义结构和该类的实例(通过new ClassName() )。 例如,有Car类,并且有具有不同属性的实例,例如里程,最大速度,马力,品牌等。 在Java上下文中,引用是一个变量*-它指向对象/实例。 例如, String s = null; s是一个引用,当前不引用任何实例,但可以引用String类的实例。 *乔恩·斯凯特(Jon Skeet)记下了变量和引用之间的区别。 见他的评论。 关于Java在调用方法时的工作方式的重要区别-传递值。 s的值是一个参考。 区分变量和值,对象和引用非常重要。 回答3 例如,当您使用关键字new , JFrame j
  • “ update”和“ update_idletasks”之间有什么区别?(What's the difference between “update” and “update_idletasks”?)
    问题 从effbot.org文档中,我们可以了解有关更新功能的以下信息: 处理所有待处理的事件,调用事件回调,完成所有待处理的几何图形管理,根据需要重新绘制窗口小部件,并调用所有待处理的空闲任务。 请谨慎使用此方法,因为如果从错误的位置(例如,从事件回调内部,或者从可以以任何方式从事件回调中调用的函数等)调用,则可能导致真正令人讨厌的竞争状况)。 如有疑问,请改用update_idletasks 。 另一方面,关于update_idletasks函数: 调用所有待处理的空闲任务,而不处理任何其他事件。 如有必要,可用于执行几何管理和重绘窗口小部件,而无需调用任何回调。 据我了解,两者都调用了所有待处理的空闲任务,完成了所有待处理的几何图形管理,并根据需要重绘了小部件。 我看到的唯一区别是update处理所有未决事件并调用事件回调。 我想这就是为什么我们不应该在偶数回调中调用update的原因。 但是,我看到了一些示例,其中update_idletasks和update update_idletasks使用,但我不明白原因,因为从理论上讲, update执行update_idletasks所做的一切。 这些未决事件和文档所讨论的空闲任务到底是什么? 有什么区别和关系? 回答了这个问题,在什么实际情况下,我应该在update_idletasks使用update ? 具体示例也被赞赏。
  • JavaScript中的$ get和$ find有什么区别?(What's the difference between $get and $find in JavaScript?)
    问题 我是一个.NET程序员,刚开始学习有关客户端脚本的更多信息,我想知道有时候您使用$get('value')和$find('value') ,但我发现它们是分别是document.getElementById('value')和Sys.Application.findComponent('value')的快捷方式。 但是,我还是不明白:这两个函数在JavaScript中有什么区别? 他们被调用时到底在查找/检索什么? 提前致谢。 回答1 $get和$find是Microsoft内置到其Ajax JavaScript库中的快捷功能。 $get是标准JavaScript GetElementById函数的缩写。 $find是.Net的findComponent()函数的缩写。 这不是标准的JavaScript函数,并且特定于Microsoft的Ajax JavaScript库。 Matt Berseth在这里很好地记录了差异和用法。 回答2 $get(elementId)返回一个DOM元素,与document.getElementById(elementId)相同 $find(elementId)返回一个ASP.NET-AJAX JavaScript对象,具有其自己的函数和属性。 不便的是,在Microsoft Ajax中,这些对象总是作为属性被附加到某个DOM元素上
  • Android中alignBaseline和alignBottom有什么区别?(What's the difference between alignBaseline and alignBottom in Android?)
    问题 我都尝试对齐一些TextView对象,它们给了我相同的结果。 “基准”和“底”之间到底有什么区别? 回答1 为了显示差异,我通常会在Word或Photoshop中想象两个文本框。 alignBottom将文本框的底部对齐。 (蓝色轮廓) 文本可能不均匀,但是它们位于其中的框会在底部对齐。 alignBaseline将框内的实际文本对齐。 这可以帮助确保文本在底部对齐,而不管字体大小或文本框大小如何。 (绿线) 什么是基准? 基线是一种印刷术术语,是指书写在其上的不可见行文本。 (如RelativeLayout中的基线是什么中所述?) 警告 如果您不小心,使用alignBaseline可能会使您的布局看起来像这样: 详细信息:注意基线对齐 我不知道您是否还在寻找答案,但我决定至少将其放在此处,因为这是第一个结果。
  • buildscript和build.gradle中的allproject之间有什么区别?(What's the difference between buildscript and allprojects in build.gradle?)
    问题 在多项目Gradle构建中,有人可以告诉我“ allprojects”部分与“ buildscript”部分之间到底有什么区别吗? 两者都有一个repositories和dependencies任务。 allprojects项目allprojects适合我的项目吗? 那buildscript呢? buildscript { repositories { ... } dependencies { ... } } 和 allprojects(subprojects) { repositories { ... } dependencies { ... } } 回答1 “ buildscript ”配置部分用于gradle本身(即,更改gradle能够执行构建的方式)。 因此,本节通常将包括Android Gradle插件。 “ allprojects ”部分适用于Gradle所构建的模块。 通常情况下,两者的存储库部分都是相同的,因为通常两者都会从jcenter(或可能是Maven Central)获取它们的依赖关系。 但是“依赖项”部分将有所不同。 通常,“ allprojects”的“ dependencies”部分为空,因为每个模块的依赖关系都是唯一的,并且将在每个模块的“ build.gradle”文件中。 但是,如果所有模块共享相同的依赖项,则可以在此处列出它们。 回答2
  • 并发,并行和异步方法有什么区别?(What is the difference between concurrency, parallelism and asynchronous methods?)
    问题 并发性是使两个任务在单独的线程上并行运行。 但是,异步方法并行运行,但在同一1个线程上运行。 如何实现的? 另外,并行性又如何呢? 这三个概念之间有什么区别? 回答1 并发和并行实际上与您正确推测的原理相同,两者都与同时执行的任务有关,尽管我会说并行任务应该是真正的多任务处理,“同时”执行,而并发可能意味着任务正在共享执行线程,而看起来仍在并行执行。 异步方法与前两个概念没有直接关系,异步用于表示并发或并行任务的印象,但实际上,异步方法调用通常用于需要完成当前应用程序工作的过程,而我们不这样做不想等待并阻止我们的应用程序等待响应。 例如,从数据库获取数据可能会花费一些时间,但是我们不想阻塞UI来等待数据。 异步调用获取一个回调引用,并在远程系统发出请求后立即将执行返回给您的代码。 当远程系统执行所需的任何处理时,您的UI可以继续对用户作出响应,一旦将数据返回给回调方法,该方法就可以适当地更新UI(或移交该更新)。 从用户角度来看,它看起来像多任务处理,但可能并非如此。 编辑 可能值得补充的是,在许多实现中,异步方法调用将导致线程被启动,但这不是必需的,它实际上取决于正在执行的操作以及如何将响应通知给系统。 回答2 简而言之, 并发是指多个任务,这些任务在重叠的时间段内以无特定顺序启动,运行和完成。 并行是指多个任务或唯一任务的多个部分实际上在同一时间(例如,在多核处理器上