少花钱搭建深度学习系统的硬件指南

栏目: 数据库 · 发布时间: 7年前

内容简介:少花钱搭建深度学习系统的硬件指南

作者:Tim Dettmers,编译:星空

由于深度学习的计算相当密集,所以有人觉得“必须要购买一个多核快速 CPU”, 也有人认为“购买快速 CPU 可能是种浪费”。

那么,这两种观点哪个是对的? 其实,在建立深度学习系统时,最糟糕的事情之一就是把钱浪费在不必要的硬件上。 本文将告诉你如何用最省钱的方式,来搭建一个高性能深度学习系统。

当初,在我研究并行深度学习过程中,我构建了一个 GPU 集群 ,所以我需要仔细选择硬件。 尽管经过了反复的研究和推理,但当我挑选硬件时,我仍然会犯许多错误,并且当应用于实践中时,那些错误就展现出来了。 所以,在这里,我想分享一下我所学到的知识,希望你不会像我一样再陷入同样的陷阱。

少花钱搭建深度学习系统的硬件指南

GPU

本文假设您将使用 GPU 进行深度学习。 如果您正在建立或升级您的系统,那么忽视 GPU 是不明智的。 GPU 才是深度学习应用的核心,它能大大提升处理速度,所以绝对不能忽略。

我在之前的文章中详细介绍了 GPU 的选择,并且 GPU 的选择可能是您的深度学习系统中最关键的选择。

一般来说,如果您的资金预算有限,我推荐您购买 GTX 680,或者 GTX Titan X(如果你很有钱,可用它做卷积)或 GTX 980(它性价比很高,但若做大型卷积神经网络就有些局限性了),它们在 eBay 上就能买得到。

另外,低成本高性价比的内存我推荐 GTX Titan。 之前我支持过 GTX 580,但是由于新更新的 cuDNN 库显着提升了卷积速度,故而所有不支持 cuDNN 的 GPU 都已经过时了,其中 GTX 580 就是这样一款 GPU。 如果您不使用卷积神经网络,GTX 580 仍然是一个很好的选择。

少花钱搭建深度学习系统的硬件指南

你能识别上面哪个硬件会导致糟糕的表现? 是这些 GPU 的其中一个? 还是 CPU?

CPU

要选择 CPU,我们首先要了解 CPU 及它与深度学习的关系。CPU 对深度学习有什么作用? 当您在 GPU 上运行深度网络时,CPU 几乎没有计算,但是 CPU 仍然可以处理以下事情:

  • 在代码中写入和读取变量
  • 执行诸如函数调用的指令
  • 在 GPU 上启动函数调用
  • 创建小批量数据
  • 启动到 GPU 的数据传输

所需 CPU 的数量

当我用三个不同的库训练深度神经网络时,我总是看到一个 CPU 线程是 100%(有时另一个线程会在 0 到 100%之间波动)。 而且这一切立即告诉你,大多数深入学习的库,以及实际上大多数的软件应用程序,一般仅使用一个线程。

这意味着多核 CPU 相当无用。 如果您运行多个 GPU,并使用 MPI 之类的并行化框架,那么您将一次运行多个程序,同时,也需要多个线程。

每个 GPU 应该是一个线程,但每个 GPU 运行两个线程将会为大多数深入学习库带来更好的性能;这些库在单核上运行,但是有时会异步调用函数,就使用了第二个 CPU 线程。

请记住,许多 CPU 可以在每个内核上运行多个线程(这对于 Intel 的 CPU 尤为如此),因此通常每个 GPU 对应一个 CPU 核就足够了。

CPU 和 PCI-Express

这是一个陷阱! 一些新的 Haswell CPU 不支持那些旧 CPU 所支持的全部 40 个 PCIe 通道。如果要使用多个 GPU 构建系统,请避免使用这些 CPU。 另外,如果您有一个带有 3.0 的主板,则还要确保您的处理器支持 PCIe 3.0。

CPU 缓存大小

正如我们将在后面看到的那样,CPU 高速缓存大小在“CPU-GPU-管线”方面是相当无关紧要的,但是我还是要做一个简短的分析,以便我们确保沿着这条计算机管道能考虑到每一个可能出现的瓶颈,进而我们可以全面了解整体流程。

通常人们购买 CPU 时会忽略缓存,但通常它是整体性能问题中非常重要的一部分。 CPU 缓存的片上容量非常小,且位置非常靠近 CPU,可用于高速计算和操作。 CPU 通常具有缓存的分级,从小型高速缓存(L1,L2)到低速大型缓存(L3,L4)。

作为程序员,您可以将其视为哈希表,其中每个数据都是键值对(key-value-pair),您可以在特定键上进行快速查找:如果找到该键,则可以对高速缓存中的值执行快速读写操作; 如果没有找到(这被称为缓存未命中),则 CPU 将需要等待 RAM 赶上,然后从那里读取该值(这是非常缓慢的过程)。 重复的缓存未命中会导致性能显着降低。 高效的 CPU 高速缓存方案和架构,通常对 CPU 的性能至关重要。

CPU 如何确定其缓存方案,是一个非常复杂的主题,但通常可以假定重复使用的变量、指令和 RAM 地址将保留在缓存中,而其他不太频繁出现的则不会。

在深度学习中,相同的内存范围会重复被小批量读取,直到送到 GPU,并且该内存范围会被新数据覆盖。但是如果内存数据可以存储在缓存中,则取决于小批量大小。

对于 128 位的小批量大小,我们对应于 MNIST 和 CIFAR 分别有 0.4MB 和 1.5 MB,这适合大多数 CPU 缓存;对于 ImageNet,我们每个小批量有超过 85 MB 的数据 ( ),即使是最大的缓存(L3 缓存不超过几 MB),也算是很大的了。

由于数据集通常太大而无法适应缓存,所以新的数据需要从 RAM 中每个读取一小部分新的,并且需要能够以任何方式持续访问 RAM。

RAM 内存地址保留在缓存中(CPU 可以在缓存中执行快速查找,并指向 RAM 中数据的确切位置),但是这仅限于整个数据集都存储于 RAM 时才会如此,否则内存地址将改变,并且缓存也不会加速(稍后你会看到的,使用固定内存时则不会出现这种情况,但这并不重要)。

深度学习代码的其他部分(如变量和函数调用),将从缓存中受益,但这些代码通常数量较少,可轻松适应几乎任何 CPU 的小型快速 L1 缓存。

从这个推理结果可以看出,CPU 缓存大小不应该很重要。下一节进一步分析的结果,也与此结论相一致。

所需的 CPU 时钟频率(frequency)

当人们想到快速的 CPU 时,他们通常首先想到时钟频率(clockrate)。 4GHz 真的比 3.5GHz 快吗?这对于具有相同架构的处理器来说,通常是正确的,例如“Ivy Bridge”。但在不同架构的处理器之间,就不能这样比较了。 此外,时钟频率也并非总是最佳的性能指标。

在深度学习上,使用 CPU 的计算很少:比如增加一些变量、评估一些布尔表达式、在 GPU 或程序中调用一些函数。以上这些都取决于 CPU 内核时钟率。虽然这个推理似乎是合理的,但是当我运行深度学习程序时,CPU 却有 100%的使用率,这是为什么? 为了找到原因,我做了一些 CPU 核频率的降频实验。

少花钱搭建深度学习系统的硬件指南

在 MNIST 和 ImageNet 上的 CPU 降频测试 :以上数据,是在具有不同 CPU 内核时钟频率时,对 ImageNet 运行 200 个周期 MNIST 数据集,或 1/4 ImageNet 周期所用时间,进行性能测量的。其中以最大时钟频率作为每个 CPU 的基准线。 为了比较:从 GTX 680 升级到 GTX Titan,性能约为 15%; 从 GTX Titan 到 GTX 980 提升 20%; GPU 超频为所有 GPU 提升约 5%的性能。

那么为什么 CPU 内核频率对系统来说无关紧要,而使用率却是 100%? 答案可能是 CPU 缓存未命中(CPU 持续忙于访问 RAM,但是同时 CPU 必须等待 RAM 以跟上其较慢的时钟频率,这可能会导致忙碌和等待两者同时存在的矛盾状态)。 如果这是真的,就像上面看到的结果一样,那么 CPU 内核的降频不会导致性能急剧下降。

另外,CPU 还执行其他操作,如将数据复制到小批量中,并将准备复制到 GPU 的数据准备好,但这些操作取决于内存时钟频率,而不是 CPU 内核时钟频率。 所以,现在我们来看看内存方面。

RAM 时钟频率

CPU-RAM,以及与 RAM 的其他交互,都相当复杂。 我将在这里展示一个简化版本的过程。为了能更全面地理解,就我们先来深入了解从 CPU RAM 到 GPU RAM 这一过程。

CPU 内存时钟和 RAM 交织在一起。 您的 CPU 的内存时钟决定了 RAM 的最大时钟频率,这两个部分构成 CPU 的总体内存带宽,但通常 RAM 本身确定了总体可用带宽,原因是它比 CPU 内存频率慢。

您可以这样确定带宽:

(其中 64 是指 64 位 CPU 架构。 对于我的处理器和 RAM 模块,带宽为 51.2GB / s)

但是,如果您复制大量的数据,这时会和带宽相关。 通常,您的 RAM 上的时序(例如 8-8-8)对于小数据量来说更为相关,并且决定您的 CPU 等待 RAM 追赶的时间。 但是如上所述,您深入学习程序中的几乎所有数据都将轻松适应 CPU 缓存,除非因为太大,才无法从缓存中获益。 这意味着计时器将是不重要的,而带宽可能才是重要的。

那么这与深度学习程序有什么关系呢? 我刚刚只是说带宽可能很重要,但是在下一步里,它就不是很重要了。 您的 RAM 的内存带宽决定了一个小批量可以被重写和分配用于初始化 GPU 传输的速度,但下一步,CPU-RAM 到 GPU-RAM 是真正的瓶颈,这一步使用直接内存存取(DMA)。 如上所述,我的 RAM 模块的内存带宽为 51.2GB/ s,但 DMA 带宽只有 12GB / s!

DMA 带宽与常规带宽有关,但细节并不一定必须了解。如果您想详细了解,可到该维基百科词条查看,您可以在词条内查找 RAM 模块的 DMA 带宽(峰值传输限制)。 但是先让我们看看 DMA 是如何工作的吧。(地址:https://en.wikipedia.org/wiki/DDR3_SDRAM#JEDEC_standard_modules)

直接内存存取(DMA)

具有 RAM 的 CPU 只能通过 DMA 与 GPU 进行通信。

在第一步中,CPU RAM 和 GPU RAM 都保留特定的 DMA 传输缓冲区;

在第二步,CPU 将请求的数据写入 CPU 侧的 DMA 缓冲区;

在第三步中,保留的缓冲区无需 CPU 的帮助即可传输到 GPURAM。

这里有人可能会想:你的 PCIe 带宽是 8GB / s(PCIe 2.0)或 15.75GB / s(PCIe 3.0),所以你应该买一个像上面所说的良好峰值传输限制的 RAM 吗?

答案是:不必要。 软件在这里会扮演重要角色。 如果你以一种聪明的方式进行一些传输,那么你就不再需要那些便宜且慢的内存。

异步迷你批量分配(Asynchronousmini-batch allocation)

一旦您的 GPU 完成了当前迷你批量的计算,它就想立即计算下一迷你批次(mini-batch)。 您现在可以初始化 DMA 传输,然后等待传输完成,以便您的 GPU 可以继续处理数字。

但是有一个更有效的方法:提前准备下一个迷你批量,以便让您的 GPU 不必等待。 这可以轻松且异步地完成,而不会降低 GPU 性能。

少花钱搭建深度学习系统的硬件指南

用于异步迷你批次分配的 CUDA 代码:当 GPU 开始处理当前批次时,执行前两次调用; 当 GPU 完成当前批处理时,执行最后两个调用。 数据传输在数据流的第二步同步之前就已经完成,因此 GPU 处理下一批次将不会有任何延迟。

Alex Krishevsky 的卷积网络的 ImageNet 2012 迷你批次的大小为 128,仅需要 0.35 秒就能完成它的完整的反向传递。 我们能够在如此短时间内分配下一批吗?

如果我们采用大小为 128 的批次,并且维度 244x244x3 大小的数据,总量大约为 0.085 GB( )。 若使用超慢内存,我们有 6.4 GB / s,即每秒 75 个迷你批次! 所以使用异步迷你批量分配,即使是最慢的 RAM 对深入学习也将足够。如果使用异步迷你批量分配,购买更快的 RAM 模块没有任何优势。

该过程也间接地意味着 CPU 缓存是无关紧要的。 您的 CPU 的快速覆盖速度(在快速缓存中),以及准备(将缓存写到 RAM)一个迷你批次其实并不重要,因为在 GPU 请求下一个迷你批次之前,整个传输就已经完成了,所以一个大型缓存真的没那么重要。

所以底线确实是 RAM 的时钟频率是无关紧要的,所以买便宜的就行了。

但你需要买多少个呢?

RAM 大小

您应该至少具有与 GPU 内存大小相同的 RAM。 当然,您可以使用较少的 RAM,但这样的话可能需要一步一步地传输数据。 然而,从我的经验来看,使用更大的 RAM 会更加方便。

心理学告诉我们,专注力是随着时间的推移会慢慢耗尽的一种资源。有些为数不多的硬件,可以帮您节省注意力资源以解决更困难的编程问题, RAM 就是其中之一。 如果您有更多的 RAM,您可以将更多的时间投入到更紧迫的事情上,而不是花费大量的时间来弥补 RAM 瓶颈。

有了很多 RAM,您可以避免这些瓶颈,节省时间并提高生产率,使注意力投入到更紧迫的地方。 特别是在 Kaggle 比赛中,我发现额外的 RAM 对于特征操作非常有用。 所以如果你资金充裕,并做了大量的预处理,那么额外的 RAM 可能是一个不错的选择。

硬盘驱动器/SSD

在某些情况下,硬盘驱动器可能是深度学习的重大瓶颈。 如果您的数据集很大,您通常会在 SSD /硬盘驱动器上放一些数据,RAM 中也有一些,以及 GPURAM 中也会放两个迷你批量(mini-batch)。 为了不断地供给 GPU,我们需要以 GPU 可以运行完的速度提供新的的迷你批量(mini-batch)。

为此,我们需要使用与异步迷你批量分配相同的想法。 我们需要异步读取多个小批量的文件,这真的很重要! 如果我们不这样做,结果表现会被削弱很多(约 5-10%),并且你精心设计的硬件优势将毫无作用(好的深入学习软件在 GTX 680 也能运行很快,而坏的深入学习软件即使用 GTX 980 也会步履维艰)

考虑到这一点,如果我们将数据保存为 32 位浮点数据,就会遇到 Alex 的 ImageNet 卷积网络遇到的数据传输速率的问题,约每 0.3 秒 0.085GB(  )即 290MB / s。 如果我们把它保存为 jpeg 数据,我们可以将它压缩 5-15 倍,将所需的读取带宽降低到约 30MB / s。 如果我们看硬盘驱动器的速度,我们通常会看到速度为 100-150MB / s,所以这对于压缩为 jpeg 的数据是足够的。

类似地,一个人可以使用 mp3 或其他压缩技术处理的声音文件,但是对于处理原始 32 位浮点数据的其他数据组,难以很好地压缩数据(只能压缩 32 位浮点数据 10-15%)。 所以如果你有大的 32 位数据组,那么你肯定需要一个 SSD,因为速度为 100-150 MB / s 的硬盘会很慢,难以跟上 GPU。

所以如果你今后有可能遇到这样的数据,那就买一个一个 SSD;如果不会遇到那样的数据,一个硬盘驱动器就足够用了。

许多人购买 SSD 是为了感觉上更好:程序启动和响应更快,并且使用大文件进行预处理也更快一些。但是对于深入学习,仅当输入维度很高且无法充分压缩数据时,才用得到 SSD。

如果您购买 SSD,您应该买一个能够容纳您常用大小的数据组的 SSD,另外还需要额外留出几十 GB 的空间。其实,让硬盘驱动器来存储未使用的数据组也是个好主意。

电源单元(PSU)

一般来说,您需要一个足够的 PSU 来满足未来的所有 GPU。 GPU 通常会随着时间的推移而更加节能,所以即使当其他组件到了更换的时候,PSU 也能继续工作很长时间,所以良好的 PSU 是一个明智的投资。

您可以通过将 CPU 和 GPU 的所需瓦数,与其他组件所需瓦数相加,再加上作为电源峰值缓冲的 100-300 瓦,就能计算出所需的瓦数。

要注意的一个重要部分,是留意您的 PSU 的 PCIe 连接器是否支持带有连接线的 8pin + 6pin 的接头。 我买了一个具有 6x PCIe 端口的 PSU,但是只能为 8pin 或 6pin 连接器供电,所以我无法使用该 PSU 运行 4 个 GPU。

另一个重要的事情是购买具有高功率效率等级的 PSU,特别是当您运行多个 GPU 并想要运行很长时间。

在全功率(1000-1500 瓦特)下运行 4 个 GPU 系统,对卷积网进行两个星期的训练,将消耗 300-500 千瓦时,而在德国的电力成本还要高出 20 美分/ kWh,即 60~100€($ 66~111)。 如果这个价格是百分之百效率的价格,那么用 80%电能训练这样一个网络会额外增加 18-26 欧元的成本! 这对于单个 GPU 来说要少得多,但在高效电源上花费更多的钱是很有意义的。

散热(Cooling)

散热是十分重要的,它可能引发另一个重要的瓶颈,比不良硬件选择更能降低性能。 您的 CPU 可以使用标准散热器,但是对于 GPU,您需要特别注意。

现代 GPU 在运行算法时,会将其速度提高到最大值,同时提高的还有功耗,但一旦 GPU 达到温度上限阈值(通常为 80°C),GPU 将降低速度从而避免突破温度阈值。 这样可以实现最佳性能,同时避免了 GPU 过热。

然而,典型的风扇速度的预编程,不是为运行深度学习程序而设计的,因此在开始深入学习程序后的几秒内,就达到了温度阈值。 结果是性能下降(约几个百分点),对于多个 GPU 而言,GPU 之间存在相互加热的情况,所以整体性能会下降 10-25%。

由于 NVIDIA GPU 是首屈一指的游戏 GPU,因此针对 Windows 进行了优化。 您可以在 Windows 中点击几下更改风扇计划,但在 Linux 中却不行,因为大多数深入学习库是为 Linux 编写的,这是一个问题。

最简单和最有性价比的解决方案是使用一个具有更合理风扇设定的 BIOS 程序刷新 GPU,这样即可以使 GPU 保持低温,也能使噪音水平达到可接受的阈值(如果使用服务器来作为解决方案,为了避免产生难以忍受的噪音,就要降低风扇的运行速度了)。

您也可能超速运行 GPU 的内存,虽然会产生 30-50MHz 的噪声,不过也是一个可行的办法。 刷新 BIO 软件是专为 Windows 设计的,但您可以使用 wine 操作系统从 Linux / Unix 操作系统调用该程序。

另一个方案是设置您的 Xorg 服务器(Ubuntu 操作系统)的配置,您可以在其中设置 “coolbits” 选项。 这对于单个 GPU 非常有效,但是如果您有多个 GPU,其中有些是 headless GPU,即没有显示器,则必须模拟一个显示器(难度非常高)。 我尝试了很长时间,并且使用实时启动 CD 来恢复我的图形设置,结果令人沮丧,程序始终无法在这个 GPU 上正常运行。

另一个更昂贵也更复杂的方案是使用水来冷却。

对于单个 GPU,即使在最大负载下,水冷却法也能降低一半温度,从而使其达不到温度阈值。甚至在多台 GPU 情况下,空气降温难以应对时,水冷却也可以很好的降温。

水冷却的另一个优点是它运行得更加默默无闻,如果工作的地方运行多个 GPU,水冷却将会具有良好的表现。 每个 GPU 的水冷却将耗费大约 100 美元,还有一些额外的前期成本(约$ 50)。 水冷还需要额外的精力来组装您的电脑,但网上有很多详细的指南手册,而且总共只需要几个小时就能搞定。后期维护很简单。

根据我的经验,我为我的深入学习集群购买过大型塔,因为他们拥有 GPU 区域的另加风扇,但我发现这在很大程度上是无关紧要的:大约只下降 2-5°C,所以不值得投资那么多钱去买这么庞大的东西。 最重要的还是直接对您的 GPU 采取降温措施:刷新 BIOS、使用水冷却法、或忍受打了折扣的运行效果。在某些情况下,以上这些都是合理的选择。 你也可以根据自己的需要找出合适的解决方案。

主板和电脑机箱

您主板应该有足够的 PCIe 端口,以支持您要运行的 GPU 数量(通常限于 4 个 GPU,即使还有多余的 PCIe 插槽); 请记住,大多数 GPU 都需要 2 个 PCIe 插槽的宽度,比如您将需要 7 个插槽来运行 4 个 GPU。 PCIe 2.0 接口对于单个 GPU 来说可以适用;但即使对于单个 GPU,PCIe 3.0 也更加经济划算; 对于多个 GPU,通常总会购买 PCIe3.0 接口,这将是一个好的决定,因为 PCIe 连接口常常是个瓶颈。

主板的选择很简单:选一个支持所需硬件配置的主板。

当您选择机箱时,您应该确保它满足 GPU 的长度要求。 大多数机箱都满足,但如果您购买小机箱,您应该多留意,要检查其尺寸和规格; 您还可以尝试用 Google 图像搜索,并查看是否在其中找到带有 GPU 的图片。

显示器(Monitors)

我刚开始也认为谈监视器是件愚蠢的事,但后来发现,它们确实有巨大的影响,而且非常重要,所以我必须要写一些关于它的内容。

我在 3 英寸 27 寸显示器上花费的钱,让我感觉到肉疼。但使用多个显示器时,效率确实提升了很多。 如果我只使用单个显示器,我感到非常困难。 千万不要在这件事上纠结,试想一下,如果您无法以更高效的方式操作,那么即使有一个特别快速的深度学习系统又有什么用呢?

当深度学习系统运行时,典型的显示器布局:左:论文,Google 搜索,gmail,stackoverflow; 中间:代码;    右:输出窗口,R,文件夹,系统显示器,GPU 显示器,待办事项列表和其他小应用程序。

少花钱搭建深度学习系统的硬件指南

当深度学习系统运行时,典型的显示器布局:左:论文,Google 搜索,gmail,stackoverflow; 中间:代码;    右:输出窗口,R,文件夹,系统显示器,GPU 显示器,待办事项列表和其他小应用程序。

建立 PC 的一些心得

很多人都害怕搭建电脑,因为硬件组件特别昂贵,谁都不想花冤枉钱。 但是有一个很简单的思路,就是不能装在一起的硬件根本无法凑合。 主板手册通常会非常具体地阐明如何组装所有部件。另外,如果您没有经验,还有大量的操作指南和视频教程指导您完成整个过程。

自己组装电脑的好处是,一旦你组装过一次,你以后就知道它是如何组装的了,因为所有的电脑都是以相同的方式组建的。组装一台电脑将会成为一种陪伴你一生的技能。 所以,立刻亲自尝试一次吧!

结论/TL; DR

GPU :GTX 680 或 GTX 960(资金有限); GTX 980(最佳性能); GTX Titan(如果你需要内存);GTX 970(无卷积网络);

CPU:每个 GPU 两个线程; 完整的 40 个 PCIe 线路和合适的 PCIe 配件(与主板匹配); > 2GHz; 快速缓冲存储区无关紧要

RAM:使用异步迷你批量配置;时钟频率和计时器并不重要; 购买至少与 GPU RAM 一样多的 CPU RAM;

硬盘驱动器/ SSD:如果您有图像或声音数据,请使用异步批处理文件读取和压缩数据;除非你使用大的输入维度的 32 位浮点数据组,否则一个硬盘驱动器就够了。

PSU: GPU+ CPU +(100-300)的总瓦数就是所需的电源供应量;如果您使用大的卷积网络,那么,就需要一个带有高效能额定功率的 PSU;另外,确保具有足够的 PCIe 接头(6 + 8pin),以及您将来可能会新购买的 GPU 所需的电量。

散热:如果您运行单个 GPU,请在您的配置中设置 coolbits 标志; 否则刷新 BIOS 以增加风扇速度是最简单和最便宜的;若想没有噪音就使用水冷却法。

主板:选择 PCIe3.0,以及选择您未来所需 GPU 数量一样多的扩展插槽数(一个 GPU 需要两个插槽,每个系统最多 4 个 GPU);

显示器:如果要升级系统以提高生产力,相对于升级 GPU,多买一台显示器可能更有意义。


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

零基础学PHP

零基础学PHP

马忠超 / 2008-3 / 56.00元

《零基础学PHP》主要内容:PHP是一种运行于服务器端并完全跨平台的嵌入式脚本编程语言,是目前开发各类Web应用的主流语言之一。PHP因其功能强大、易学易用、可扩展性强、运行速度快和良好的开放性,而成为网站开发者的首选工具,其较高的开发效率,也给开发人员在编写Web应用程序时带来极大的便利。一起来看看 《零基础学PHP》 这本书的介绍吧!

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码

URL 编码/解码
URL 编码/解码

URL 编码/解码

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具