1.简介

我们相信实时嵌入式软件的解决方案是对处理器架构的重新思考。正如在其他[9]中所讨论的,现在是时候考虑那些提供与功能一样可预测定时的架构了。在本文中,我们提出了这样一个精确定时(PRET)架构的具体示例:一个基于SPARC指令集架构(ISA)的多线程处理器,它提供可预测的定时以及可预测的功能和性能。下面,我们使用SystemC[23]和一个在其上运行的应用程序来演示软件如何利用PRET体系结构,从而给出一个周期精确级的PRET体系结构模型。

2.PRET的哲学

PRET的哲学是,时间特征应该像功能一样可以预测。就像处理器上的算术始终是一致的、可预测的和文档化的一样,我们希望它的速度也同样是一致的、可预测的和文档化的。(将时钟拨回8位微处理器时代是实现这一目标的一个很有效的方法)但PRET的目标是:如何使许多高集成级别的现代体系结构具有可预测性。

因此,PRET支持软件管理的暂存存储器[3],线程交错的管道,没有旁路[20,11],ISA级别的显式定时控制[15],具有全局时间同步[16]的时间触发通信[17],以及具有显式定时[14]的高级语言。在本文中,我们提出了一个包含许多租户的体系结构,并演示了如何对其进行编程。特别是,我们将重点放在将计时指令集成到线程交错的管道和可预测的内存系统上。然后,我们将展示如何编写这样一个可预测的体系结构。

3.相关工作

Agarwal等人的原始处理器[29]分享了PRET哲学的某些元素。它也使用了一个软件管理的暂存器替代指令缓存[22],并且肯定考虑了通信延迟(“raw”这个名称提醒人们,它的ISA暴露于线路延迟)。

原始架构被设计成一个由单线程处理器通过一个新的互连网络连接组成的网格。虽然我们为高端PRET处理器设想了类似的配置,但我们在这里提供的实现不考虑内核间通信。未来我们可能会采用类似raw的通信网络。

Java优化的处理器[27]支持精确的最坏情况执行时间界限(不支持控制执行时间)。SPEAR[8]处理器禁止条件分支。REMIC[26]和KIEL[21]在PRET意义上是可预测的,但它们只允许Esterel[5]作为入口语言。上述等等,我们发现实现实时的限制条件太多了;我们工作的中心目标是提供一个C开发环境。

Ip和Edwards[15]首先在一个非常简单的非流水线处理器中实现了deadline指令,该处理器不支持C编译器。这个deadline指令允许用编程的方法来指定程序代码段的下限执行时间。我们的工作通过借用deadline指令语义并将其集成到一个线程交错的管道中,从而将他们的工作扩展到一个新的架构。我们引入了一种重放机制来使得在不阻塞整个管道的情况下阻塞特定的线程。在deadline指令中再次使用这种重放机制。

Giotto语言[14]是一种在软件级别指定系统定时的新方法。但是,它依赖于通常的RTOS基础结构,该基础结构假定已知最坏情况下的执行时间来建立可调度性[7]。我们的PRET处理器将是Giotto编程环境的理想目标。

线程交错的管道至少可以追溯到1987年的[20],甚至更早。线程交错减少了处理器的面积、功耗和复杂性[11,18],但更重要的是,它促进了管道中指令的可预测执行。在线程交错的管道中对主内存的访问通常是管道的[11,18],但是现代的大型内存通常不是管道的,因此我们的方法为每个线程提供一个窗口,在这个窗口中线程可以访问主内存。这提供了对内存的可预测访问和线程之间的互斥。我们称之为记忆轮。

Mueller等人的[2]虚拟简单体系结构的目标是实现不可预测的处理器的硬实时操作。它们在一个快速、不可预测的处理器上运行实时任务,同时在一个较慢、更可预测的处理器上运行实时任务,如果速度慢的处理器超过了速度快的处理器,它们就会切换。优点是更快的处理器将有时间运行额外的、非时间关键的任务。相比之下,我们的PRET方法保证了详细的时间安排,而不仅仅是任务完成时间,而是允许使用时间安排进行同步

暂存式存储器长期以来一直被提议用于嵌入式系统,因为它比缓存[4]消耗更少的能量,但在这里,我们采用暂存式存储器纯粹是因为它们能够更好地预测。由于暂存式存储器是软件管理的,因此内存分配方案的问题变得很重要。我们未来的工作是:在当前PRET架构的基础上开发内存分配方案。

Figure 1:PRET架构框图

4.我们的架构

在本节中,我们将介绍PRET处理器、其内存系统和ISA扩展的设计,以支持截止日期计数器。我们使用循环精确的SystemC[23]模型对PRET体系结构(如图1所示的框图)进行了原型化,该模型执行C代码,并使用GNU C编译器进行编译。我们的模拟器实现了一个扩展的SPARC v8 ISA[28]。

图1中的PRET处理器组件实现了一个六阶段的线程交错管道,其中每个阶段执行一个单独的硬件线程,这样可以避免使用旁路[20,11]。每个硬件线程都有自己的寄存器文件、本地片内存储器和指定的片外存储器区域。线程控制器组件是一个简单的循环线程调度器——在任何时候,每个线程只占用一个管道阶段。为了可预见地处理管道的停顿,我们引入了一种重播机制,它简单地重复相同的指令,直到操作完成。因此,一个线程的停顿不会影响其他线程。线程的循环执行避免了内存一致性问题

内存层次遵循哈佛架构[13],它由用于指令和数据的,独立的快速片上暂存存储器(SPM)和一个大的片外主存组成。它们连接到一个直接内存访问(DMA)控制器,该控制器负责在主存和SPMs之间移动数据。目前,我们假设程序代码完全适合SPMs,因为我们还没有开发一个自动程序内存管理方案[3]。DMA组件目前仅在打开电源时将每个线程的程序代码和数据从主内存传输到各自的spm。如前所述,内存读写使用重放机制。每个线程都有自己的访问窗口,由内存轮管理。如果一个线程错过了它的窗口,它就会阻塞,直到它的窗口到达。

我们将一个deadline指令[15]合并到基于sparc的ISA中。这样的指令阻塞,直到软件可编程截止计数器达到零。每个计数器由一个线程本地锁相环控制,该锁相环可以通过编程以系统时钟频率的合理倍数计数。下面,我们将详细描述我们的实现。介绍了内存系统、内存轮、内存映射、线程交错流水线、时序指令扩展和工具链流程。

4.1.内存系统

众所周知,缓存是造成[30]定时不确定性的主要原因,但是简单地删除它们是不可接受的。相反,我们使用暂存器来弥补处理器内存的缺口。暂存存储器是硬实时嵌入式处理器中常用的软件管理的片上存储器。spm由软件通过DMA传输进行管理,从而避免了不可预测性(通常是微妙的)硬件替换策略。每个线程本地SPM为64 KB,周期延迟为1。我们使用一个16 MB的主内存,我们假设它的实际延迟是50纳秒。这意味着在大约250 MHz的PRET处理器上运行12.5个周期,我们将其四舍五入为13个周期。

如果所有线程都能够在任意时间访问片外主存,则一个线程的片外内存访问时间可能取决于另一个线程的内存访问模式。这种类型的行为引入了时间的不可预测性,是不受欢迎的。为了确保可预测的时间,所有对主存的读写操作,例如共享数据,都必须通过我们的内存轮来完成。与视差螺旋桨芯片[24]中的“中心”一样,这个轮子也有一个固定的轮询调度来决定哪个线程可以访问内存。根据固定的调度和线程请求访问主内存的时间,访问可能需要13到90个周期。需要注意的是,确切的循环数只取决于发出请求的周期,而不取决于其他线程或内存访问模式的行为。

我们使用管道部分中描述的重播机制,而不是在多周期内存访问期间阻塞整个管道。一个简单的内存管理单元在spm、主内存和基于地址的内存映射I/O之间进行选择。

4.1.1.内存轮

内存轮以确定性和可预测的方式控制对芯片外主存储器的访问。每个线程被分配一个13周期的窗口,在这个窗口中它必须完成它的内存访问;轮调度每78个周期重复一次。如果一个线程在它的窗口的第一个周期开始访问,那么访问需要13个周期。否则,线程阻塞,直到它的窗口重新出现,这可能需要77个周期。错过窗口的第一个周期后成功访问将导致77 + 13 = 90个周期。虽然这种机制会导致线程阻塞,但是没有线程间的交互,窗口的行为是可预测的。

4.1.2.内存映射

Figure 2:内存图

  • Boot code:这个地址空间包含每个线程在启动时使用的引导代码,用于初始化所有寄存器并跳转到线程程序的开始。
  • Shared data (8 MB):这个地址范围在我们的方案中是为多线程共享的数据保留的。
  • Thread-local instructions and data (1 MB per thread):第一个线程从地址0x40000000开始。512KB用于指令,512KB用于数据。每个后续的线程都从其前一个线程的偏移量0x100000字节开始。这意味着第一个线程包含地址从0x40000000- 0x400FFFFF,第二个0x40100000- 0x401FFFFF,以此类推。这种方法允许任何内存位置中的每个数据字节都与一个地址唯一关联。
  • Memory-mapped I/O:我们保留0x80000000以上的地址用于特殊目的,比如内存映射。特别是,我们按照映射地址0x80000200到达UART,这与我们的工具链的GCC为printf或put生成的内容一致。

图2显示了系统内存映射(地址是32位)。系统中的每一块内存都有一个惟一的全局地址(主内存和SPMs),但是每个线程只能访问整个内存映射的一部分。地址0x3F800000 - 0x405FFFFF (14 MB)是主内存,每个线程都可以看到它。这种布局考虑到了未来的扩展:共享数据空间可以向下扩展;线程本地内存可以向上扩展。我们当前的实现有512字节的引导代码、8 MB的共享数据和1 MB的SPMs总量。外围设备从0x80000000开始;我们在0x80000200处放置了一个UART。

4.2.管道

我们的架构实现了一个支持六个独立硬件线程的六阶段线程交错管道。每个线程都有自己的一组寄存器。通过设计,我们为每个管道阶段实现了一个线程,以消除同一线程中指令之间的依赖性。因此,它不需要任何数据危险检测逻辑或旁路。

线程控制器根据一个roundrobin策略调度线程,并将线程标识符传递给管道以索引特定于线程的寄存器和SPMs。在获取阶段,从SPM获取当前的程序计数器(PC)。由于线程交错,我们不需要为当前线程更新下一个PC,所以直到当前线程离开管道前,它不会被获取。因为当PC被获取时,我们确信它总是正确的,这消除了任何投机执行的需要;译码阶段对指令进行译码并设置相应的流水线控制。regacc阶段从寄存器文件中读取源操作数,并在操作数的立即数据和注册数据之间进行选择。execute阶段执行ALU操作。mem阶段访问SPM或主内存。except阶段捕获异常,如果没有异常,则将任何结果写入寄存器文件。在根据stalls和分支,确定下一个值后,我们也在这个阶段更新PC。

即使我们不需要数据危害检测,我们也必须考虑结构危害检测。我们使用重播机制来处理它们,我们将在下面详细说明。

4.2.1.Stalls和重播机制

我们的管道只更新except阶段中的寄存器。此阶段仅在未发生异常的情况下将数据写入寄存器文件。这为每个线程提供了一个提交点。我们在这个提交点决定是否需要重放一个指令。

通过重放指令,我们可以确保每个线程在前进之前每个循环只停留在一个管道阶段,甚至对于多循环操作(如内存访问)也是如此。例如,在内存停止时,停止的指令每六个周期重复播放一次,直到从内存中取出数据,并且线程可以继续。因此,重播提供了一种可预测的方法来独立地阻塞线程,而不是阻塞整个管道。except阶段检查一条指令的重放位,只有当重放位为空时才提交。否则,获取阶段检查并确定下一个要获取的PC。因此,该线程的下一个迭代将重新运行相同的指令,直到多周期操作完成。

4.3.时间说明

为了给软件提供精确的定时控制,我们添加了一个“deadline”指令,允许程序员设置和访问周期精确的计时器[15]。这条指令为一段代码的执行时间设置了一个下限期限。我们提供了两种类型的截止时间计时器,可以通过这个指令访问:一组根据主时钟计数,另一组根据可编程锁相环(PLL)产生的时钟计数。这些计时器实际上就是:只能通过deadline指令访问的附加寄存器(图1)。

4.3.1.语法

我们采用了来自Ip和Edwards[15]的deadline指令的语法。有一个直接形式:deadi\: \: $t_i,v和一个注册形式:dead\: \: \$t_i, \$r_j。每个线程有12个deadline寄存器(t_0-t_{11}),其中8个寄存器计算指令周期,其他4个寄存器由锁相环驱动;和32个全局寄存器(r_0-r_{31})。v是一个13位的即时值。

4.3.2.语义

最后期限指令只能对代码段的执行时间施加一个下界;使用重播,当写的最后期限寄存器不是0时,最后期限指令阻塞线程。

与Ip和Edwards[15]不同的是,我们的处理器是流水线的,所以我们每六个时钟周期减少一次注册截止时间。而锁相环则以锁相环所设定的速率注册。当一个deadline指令试图设置一个deadline寄存器时,它会阻塞,直到deadline寄存器为零,这时它会重新加载寄存器并将控制权交给下一条指令。因此,较早的deadline指令可以设置下一个deadline指令终止之前的最小时间间隔。

目前,如果最后期限已过(即,寄存器在deadline指令到达之前为零),我们什么也不做:deadline指令只是立即加载新值并继续。稍后,我们计划允许架构在错过最后期限时抛出异常。

4.3.3.实现

为了实现deadline指令,我们选择了一个未使用的操作码,并遵循了通常的SPARC指令编码格式,该格式允许我们同时包含指令的寄存器和直接形式。图5显示了两个具体的编码。

支持deadline指令需要一些额外的管道控制逻辑和deadline寄存器。

在我们的管道中,我们在寄存器访问阶段检查deadline寄存器,并使用重播机制阻塞deadline指令,直到它的deadline寄存器为零。

4.4.编译流

我们采用了开源LEON3实现[12]使用的SPARC工具链。图3显示了我们的编译流程。

我们要求用户在单独的文件(例如thread0.c)中为每个硬件线程提供main()函数。通过将-Ttext和-Tdata选项传递给链接器,我们在内存映射指定的位置编译它们。例如,thread0.c从地址0x40000000开始,而thread1.c从0x40010000开始。我们将生成的目标文件与设置代码合并,并将其转换为Motorola S-record (SREC)格式。然后,我们的模拟器使用SREC文件的内容初始化内存。我们计划使用相同的SREC文件作为PRET处理器的FPGA实现的输入。

5.基本PRET编程

为了说明如何将PRET计时精度用于同步,我们提供了一个简单的生产者/消费者示例,其中有一个显示传输数据的观察者。这是一个典型的互斥问题,因为我们必须处理共享资源的问题。但是,与传统方法不同,在我们的方法中,线程必须等待锁的时间是确定的,因为它不依赖于其他线程访问锁的行为。

我们的方法使用截止日期计数器和指令定时的精确知识来同步对用于通信的共享变量的访问。我们采用最坏情况执行时间(WCET)分析工具来分析从C程序生成的指令,并计算最后期限计数器的确切值,以确保正确的同步。

5.1.互斥

跨不同线程管理共享数据的一般方法是使用互斥的临界区,这些临界区一次只能由单个线程访问。我们的内存轮已经确保对共享单线程的任何访问都是原子性的,因此我们只需确保这些访问按正确的顺序进行。

图4显示了生产者、消费者和观察者访问共享变量buf的C代码(下划线)。生产者迭代并向共享数据写入一个整数值。消费者从这个共享数据中读取这个值并将其存储在一个数组中。为简单起见,我们的使用者不会对所使用的数据执行任何其他操作。它只是将数据存储在数组中。观察者还读取共享数据并将其写入到内存映射外围设备。

图4中的deadline指令用粗体标记。我们在每个线程的开头使用交错的最后期限来抵消线程,并强制生产者在消费者和观察者之前开始。在每个线程内部,最后期限强制每个循环彼此同步运行,每个线程以相同的速度前进。每个循环迭代首先执行生产者的临界部分,然后并行执行观察者和消费者。

达到这个目的的补偿是由项目开始时的最后期限给出的。相对于使用者和观察者来说,41∗6 = 246周期的最后期限是相同的,这迫使这两个线程同时进入循环。这个值是从汇编语言指令计算出来的,它是使用者线程所能完成的最小截止日期。生产者循环的偏移量是28∗6 = 168个周期,这比使用者和观察者的246个周期的偏移量少78个周期。由于此差异与轮转调度重复的频率相同,因此可以保证生产者线程在轮转的较早阶段访问共享数据。

一旦进入循环,最后期限迫使每个线程以相同的速度运行,从而维护内存访问计划。重要的是,这个速度是轮速度的倍数,以保持时间表。在本例中,我们希望每个循环迭代对轮子进行两次旋转。这允许我们在第一次轮询时写入缓冲区,并在第二次轮询时为使用者和观察者执行读操作。这也意味着,无论哪个C线程被划分到哪个硬件线程,我们的程序都将正确运行。为了实现这一点,我们将每个循环的截止日期设置为26,因为26*6 = 156循环正好对应轮子的两次旋转。

引用

[1] Malardalen WCETproject / Benchmarks. Website: http://www.mrtc.mdh.se/projects/wcet/benchmarks.html.

[2] A. Anantaraman, K. Seth, K. Patil,E. Rotenberg, and F. Mueller. Virtual SimpleArchitecture (VISA): Exceeding the Complexity Limit in SafeReal-Time Systems. In Proceedings of the International Symposium on Computer Architecture (ISCA), pages 350–361, San Diego, California, June 2003.

[3] O. Avissar, R. Barua, and D. Stewart. An optimal memory allocation scheme for scratchpad-based embedded systems. ACMTransactions on Embedded Computing Systems, 1(1):6–26, 2002.

[4] L. Benini, A. Macii, E. Macii, and M. Poncino. Increasing Energy Efficiency of Embedded systems by Application-Specific Memory Hierarchy Generation. IEEE Design & Test of Computers, 17(2):74–85, April-June 2000.

[5] G. Berry and G. Gonthier. The ESTERELsynchronous programming language: design, semantics, implementation. Science of Computer Programming, 19(2):87–152, 1992.

[6] H. Berry, D. G. Pérez, and O. Temam. Chaos incomputer performance. Chaos: An Interdisciplinary Journal of Nonlinear Science, 16(013110):1–15, Jan. 2006.

[7] E. Bini and G. C. Buttazzo. Schedulability analysis of periodic fixed priority systems. IEEE Transactions on Computers, 53(11):1462–1473, 2004.

[8] M. Delvai, W. Huber, P.Puschner, and A. Steininger. Processor support for temporal predictability-the SPEAR design example. Real-TimeSystems, 2003. Proceedings. 15th Euromicro Conference, pages 169–176, 2003.

[9] S. A. Edwards and E. A. Lee. The case for the precision timed (PRET)machine. In Proceedings of the 44th Design Automation Conference, pages 264–265, SanDiego, California, June 2007.

[10] C. Ferdinand, R. Heckmann, and et. al. Reliable and precise WCETdetermination for a real-lifeprocessor. In Proceedings of the International Conference on Embedded Software (EMSOFT),volume 2211 of Lecture Notes in Computer Science, pages 469–485, North Lake Tahoe, California, Oct. 2001.

[11] B. Fort, D. Capalija, Z. Vranesic, and S. Brown. A Multithreaded Soft Processor for SoPC Area Reduction. Proceedings of the 14th Annual IEEESymposium on Field-Programmable Custom Computing Machines (FCCM’06)-Volume00, pages 131–142, 2006.

[12] Gaisler Research. LEON3Implementation of the SparcV8. Website: http://www.gaisler.com.

[13] J. L. Henessey and D. J. Patterson. Computer Architecture: A Quantitative Approach. Morgan Kaufmann Publishers, third edition, 2003.

[14] T. A. Henzinger, B. Horowitz, and C. M. Kirsch. Giotto: A time-triggered language for embedded programming. In Proceedings of the First International Workshop on Embedded Software (EMSOFT),volume LNCS2211, Tahoe City, CA, 2001. Springer-Verlag.

[15] N. J. H. Ip and S. A. Edwards. A processor extension for cycle-accurate real-time software. In Proceedings of the IFIP International Conference on Embedded and Ubiquitous Computing (EUC), volume 4096 of Lecture Notes in Computer Science, pages 449–458, Seoul, Korea, Aug. 2006.

[16] S. Johannessen. Time synchronization in alocal area network. IEEEControl Systems Magazine, pages 61–69, 2004.

[17] H. Kopetz and G. Grünsteidl. TTP — A Protocol for Fault-Tolerant Real-Time Systems. IEEEComputer, 27(1):14–23, Jan. 1994.

[18] M. Labrecque and J. G. Steffan. Improving pipelined soft processors with multithreading. In 7th International Conference on FieldProgrammable Logic and Applications (FPL),Amsterdam, Netherlands, August 2007.

[19] A. LaMothe. Game Programming for the Propeller Powered HYDRA.Parallax, Inc., Rocklin, California, 2006.

[20] E. A. Lee and D. G. Messerschmitt. Pipelineinterleaved programmable DSP’s: Architecture. IEEE Transactions on Acoustics, Speech, and Signal Processing, ASSP-35(9):1320–1333, Sept. 1987.

[21] X. Li, J. Lukoschus, M. Boldt, M. Harder, and R. von Hanxleden. An Esterel processor with full preemption support and itsworst case reaction time analysis. Proceedings of the 2005 International Conference on Compilers, Architectures and Synthesis for Embedded Systems, pages 225–236, 2005.

[22] J. Miller and A. Agarwal. Software-based instruction caching for embedded processors. InProceedings of the International Conference on Architectural Support for Programming Languages and Operating Systems (ASPLOS), pages 293–302, San Jose, California, Oct. 2006.

[23] OSCI. SystemC Simulation Library. Website: http://www.systemc.org.

[24] Parallax Inc. Propeller Manual. Website: http://www.parallax.com/Portals/0/Downloads/docs/ prod/prop/WebPM-v1.01.pdf.

[25] D. A. Pattersonand D. R. Ditzel.The case for the reduced instruction set computer. ACMSIGARCH Computer Architecture News, 8(6):25–33, Oct. 1980.

[26] Z. Salcic, D. Hui, P. Roop, and M. Biglari-Abhari. REMIC: design of a reactive embedded microprocessor core. Proceedings of the 2005 conference on Asia South Pacific design automation, pages 977–981, 2005.

[27] M. Schoeberl. JOP: A Java Optimized Processor. Workshop on Java Technologies for Real-timeand Embedded Systems (JTRES2003), Catania, Sicily, Italy, November, 2003.

[28] SPARC International Inc. SPARCStandards. Website: http://www.sparc.org.

[29] M. B. Taylor, J. Kim, and et al. The Raw microprocessor: A computational fabric for software circuitsand general purpose programs. IEEEMicro, 22(2):25–35, March/April 2002.

[30] L. Thiele and R. Wilhelm.Design for Timing Predictability. Real-TimeSystems, 28(2):157–177, 2004.

[31] B. J. Welch, S. O. Kanaujia, A. Seetharam, D. Thirumalai, and A. G. Dean. Supporting demanding hard-real-time systems with STI.IEEE Transactions on Computers,54(10):1188–1202, Oct. 2005.

总结

PRET架构只是实现了相对时间,没有实现绝对时间。

Predictable Programming on a Precision Timed Architecture相关推荐

  1. Tight WCRT Analysis of Synchronous C Programs

    1.简介 在过去的十年中,无处不在的嵌入式系统引起了研究人员的注意.典型的嵌入式应用,从复杂的飞机飞行控制器到简单的数码相机,都需要对它们的定时性能做出最坏的保证,因此被称为实时系统.实时系统设计的标 ...

  2. PRET-C:一种用于精确定时架构的编程新语言

    1.摘要 精确定时架构(PRET)是最近提出的一种设计实时嵌入式系统处理器的方案.这些处理器必须在不牺牲吞吐量的情况下保证应用程序的精确最坏情况反应时间(WCRT),并且必须允许程序的WCRT的计算既 ...

  3. Multi-Runtime Microservices Architecture

    Key Takeaways Creating distributed systems is not an easy task. Best practices have emerged around & ...

  4. 64位Linux的内核和用户地址空间

    32位的Linux中,0x00000000-0xBFFFFFFFFF 这3GB是 用户空间 0xC00000000-0xFFFFFFFFFF 这1GB是 内核空间 ++++++++++++++++++ ...

  5. 诺丁汉大学计算机专业介绍,诺丁汉大学计算机科学本科专业.pdf

    诺丁汉大学计算机科学本科专业.pdf 留学监理服务网 诺丁汉大学 计算机科学 - Computer Science 基本信息 诺丁汉大学 - The University of 所属学校 所在院系 理 ...

  6. 如何构建一个简单的图书推荐系统

    原作者:venkat-raman 出处:https://www.linkedin.com/pulse/content-based-recommender-engine-under-hood-venka ...

  7. 我手中的电子书书目清单(开始提供BT下载)

    13G电子书开始提供BT下载,下载说明及BT种子下载见我另一Blog网页:http://blog.csdn.net/yiyuan/archive/2005/10/16/504747.aspx 我手中的 ...

  8. yiyuan编程电子书系列(目录及种子)

    感觉不错,整个一个电子书库,与大家一起分享一下 BT下载地址: YiYuan编程电子书系列1 http://nnv.dl1.btchina.net/download.php?s=38fff1692d9 ...

  9. 全球计算机科学硕士申请,2020年爱丁堡大学计算机科学专业硕士申请条件-学费-世界排名...

    1.选修课: 有超过50门选修课可供选择,如: Machine Learning and Pattern Recognition Probabilistic Modelling and Reasoni ...

最新文章

  1. IOS -- base64编码
  2. [spfa][差分约束] 洛谷 P3084 照片Photo
  3. python中__init__文件的运用_python中__init__.py文件的作用
  4. 【沫沫金】安卓手机版 - 日期控件
  5. C++进阶教程之动态内存
  6. Getting a handle on
  7. 程序员双十一都该买点啥?
  8. Neo4j Louvain算法
  9. matlab 对数函数表示,matlab对数函数怎么表示
  10. 车载ECU软件刷新flash driver制作
  11. resample按时间聚合
  12. CSMA/CD总线以太网和交换式以太网
  13. v-viewer 插件图片点击放大预览的几种使用方法
  14. Layer js——弹窗/提示/询问/加载/层
  15. 已知差异脑区MNI坐标,如何将MNI坐标转化为AAL分区和布罗得曼分区Brodmann area名称
  16. java 航班_Java实现简单航班查询系统-Go语言中文社区
  17. 水笔:20年好用软件或者工具备忘
  18. Leetcode 500题AC的刷题总结(C与C++)
  19. 机器学习实战-42: 非线性回归算法(Non-linear Regression)
  20. 沈博阳:互联网创业者在中国生存必须有坚韧素质

热门文章

  1. UE5 官方案例Lyra 全特性详解 9.蓝图消息系统
  2. 基于Java+SpringBoot+Thymeleaf+Mysql在线教育视频点播学习系统设计与实现
  3. 【持续更新】Jetson Nano 人工智能机器人开发实战案例——RosmasterX3A1
  4. sourcetree 已贮藏误删如何恢复
  5. HostMonitor安裝RMA for Linux监控Linux系统资源
  6. 2019 11 14
  7. 创客学院知识巩固-05ARM硬件工作原理
  8. Display P3
  9. Python UnitTest接口自动化实战
  10. fedora如何隐藏顶部状态栏_桌面便签如何始终保持显示,便签如何在桌面显示