网易首页 > 网易号 > 正文 申请入驻

北大校友“炼丹”分享:OpenAI如何训练千亿级模型?

0
分享至

编译 | 琰琰

大规模深度神经网络训练仍是一项艰巨的挑战,因为动辄百亿、千亿参数量的语言模型,需要更多的 GPU 内存和时间周期。这篇文章从如何多GPU训练大模型的角度,回顾了现有的并行训练范式,以及主流的模型架构和内存优化设计方法。 本文作者Lilian Weng现为OpenAI应用人工智能研究负责人,主要从事机器学习、深度学习和网络科学研究 。她本科毕业于香港大学,硕士就读于北京大学信息系统与计算机科学系,之后前往印度安纳大学布鲁顿分校攻读博士。 Lilian Weng经常在个人博客分享学习和工作笔记,感兴趣的可以戳这里: https://lilianweng.github.io/lil-log/。

“炼大模型”已成为人工智能领域的主流研发趋势。从GPT-3的1750亿,到如今悟道2.0的1.75万亿,超大语言模型在 NLP 基准任务中不断刷新SOTA。

然而,参数和数据集的快速增长让 GPU 算力开始捉襟见肘。单个GPU内存已经远远不能满足大模型的需求。如,阿里用480块GPU训练千亿模型;英伟达用3072块GPU训练万亿模型;谷歌用2048块TPU训练1.6万亿模型(1 TPU约等于2~3 GPU)。

如何利用上百块GPU上训练大规模语言模型?并行计算是一种行之有效的方法。

近日,OpenAI 研究员Lilian Weng分享干货文章,从并行训练(数据并行、模型并行、管道并行、张量并行)、混合专家、内存节省设计(CPU卸载、重新激活计算、混合精度训练、高效存储优化器)三个方面回顾了现阶段多GPU训练大模型的主流方法。

AI科技评论这篇文章编译如下,供想成为“炼丹师”的朋友参考。

1

并行训练

大规模神经网络模型对存储空间有强烈的需求,单个GPU的内存已经远远不够。究其原因,一方面模型权重有数百亿个浮点数,随机梯度下降和Adam优化需要极高的计算成本;另一方面在预训练阶段,大模型与大规模语料库的配对需要很长的时间周期。综合来看,跨GPU并行计算显得尤为重要。

并行计算在数据、模型架构和张量等不同维度上都可以操作,接下来本文将具体介绍一些主流方法:

数据并行

数据并行( Data parallelism ,DP)最简单的方法是将相同的模型权重复制到worker节点,并分配一部分数据以同时进行处理。我们知道,如果模型的参数量大于单个GPU节点的内存,DP无法正常工作,GeePS架构(Cui等人,2016)的解决思路是使用有限的GPU内存。也就是,如果模型太大无法嵌入到一台机器,就将暂时未使用的参数卸载回CPU。

数据交换传输通常在后端进行(不干扰训练计算),在每个Mini-batch计算结束后,worker需要同步梯度或权重,以保证学习效率。现有的同步方法有两种,各自优缺点如下:

1、批量同步并行(BSP):worker在每个Mini-batch结束时同步数据,这种方法保证了模型权重传递的及时性,但每台机器都必须排队等待其他机器发送梯度。

2、异步并行(ASP):每个GPU采用异步方式处理数据,这种方法避免了不同机器之间的相互等待或暂停,但影响了权重传递的时效,降低了统计学习效率。而且即使增加计算时长,也不会加快训练的收敛速度。

在中间某些地方的每一次迭代(>1)都需要同步全局梯度。自Pytorch v1.5版(Li等人,2021年)提出后,该特征在分布式数据并行(Distribution Data Parallel,DDP)中被称为“梯度累积(gradient accumulation)”。分桶梯度(bucketing gradients)避免立即执行AllReduce操作,而是将多个梯度存储到一个AllReduce中以提高吞吐量,并基于计算图优化计算和通信调度。

图1:Pytorch DDP的伪代码(来源:Li等人,2021年)

模型并行

模型并行(Model parallelism,MP)用于解决模型权重不能适应单个节点的情况,在这里,计算和模型参数都需要跨多台机器进行处理。在数据并行中,每个worker承载着整个模型的完整副本,而MP只在一个worker上分配部分模型参数,因此对内存和计算的需求要小很多。

深度神经网络包含一堆垂直层,如果逐层拆分将连续的小层分配到工作层分区,操作起来并不难,但通过大量具有顺序依赖性的Workers来运行每个数据batch会花费大量的时间,计算资源的利用率也严重不足。

图2:一个包含4个垂直层的模型并行设置,由于顺序的依赖性,每个数据依次由一个worker处理,这个过程会出现大量多余时间“气泡”(来源:Huang等人,2019年)

管道并行

管道并行(Pipeline parallelism,PP)是将模型并行与数据并行结合起来,以减少低效时间“气泡”的过程。主要思想是将Mini-batch拆分为更多个微批次(microbatch),并使每个阶段worker能够同时处理。需要注意的是,每个微批次需要两次传递,一次向前,一次向后。worker分区的数量称为管道深度,不同worker分区之间的通信仅传输激活(向前)和梯度(向后)。这些通道的调度方式以及梯度的聚合方式在不同的方法中有所不同。

在GPipe(Huang et al.2019)方法中,多个微批次处理结束时会同时聚合梯度和应用。同步梯度下降保证了学习的一致性和效率,与worker数量无关。如图3所示,“气泡”仍然存在,但比图2少了很多。给定m个均匀分割的微批次和d个分区,假设每个微批次向前和向后都需要一个时间单位,则气泡的分数为:

GPipe论文表明,如果微批次的数量超过分区数量4倍(m>4d),则“气泡”开销几乎可以忽略不计。

图3:带有4个微批次 和4个分区的GPipe的并行管道(来源:Huang等人,2019年)

GPipe在吞吐量方面与设备数量成线性关系,设备数量越多,吞吐量越大。不过,如果模型参数在worker中分布不均匀,这种线性关系不会稳定出现。

PipeDream(Narayanan等人,2019年)方法要求每个worker交替处理向前和向后传递的消息(1F1B)。它将每个模型分区命名为“stage”,每个stage worker可以有多个副本来并行运行数据。这个过程使用循环负载平衡策略在多个副本之间分配工作,以确保相同minibatch 向前和向后的传递发生在同一副本上。

图4:PipeDream中1F1B微批次调度的图示(来源:Harlap等人,2018年)

由于PipeDream没有在所有worker batch结束时同步全局梯度,1F1B 很容易导致不同版本的模型权重的微批次向前和向后传递,降低学习效率。对此,PipeDream提供了一些解决的思路:

  • 权重存储:每个worker跟踪多个模型版本,给定数据 batch 的向前和向后传递相同版本的权重。

  • 垂直同步:不同模型权重版本与激活和梯度一起在全局worker之间传递,计算采用上一个worker传播的相对应的隐藏版本。这个过程确保了worker之间的版本一致性(不同于GPipe,采用异步计算)。

在训练开始时,PipeDream会先分析模型每一层的计算内存和时间成本,然后将层划分为不同的stage进行优化。

图5:上图为VGG16在ILSVRC12上的运行结果,ASP=异步并行,BSP=批量同步并行;下图为不同并行配置的训练时间加速度(来源:Harlap等人,2018年)

后来有学者提出了PipeDream两种变体,主要思路是通过减少模型版本来缓解内存占用(Narayanan等人,2021年)。其中,PipeDream-flush增加了定期刷新全局同步管道的功能,就像GPipe一样,这种方式虽然牺牲了一点吞吐量,但显著减少了内存占用(例如仅需要维护单一版本的模型权重)。

图6:PipeDream flush中管道调度图示(来源:Narayanan等人,2021年)

PipeDream-2BW维护两个版本的模型权重,“2BW”代表“双缓冲权重(double-buffered weights)”,它会在每个微批次生成一个新的模型版本K(K>d)。由于一些剩余的向后传递仍然依赖于旧版本,新的模型版本无法立即取代旧版本,但因为只保存了两个版本,内存占用的也被大大降低了。

图7:PipeDream-2BW 中的流水线调度示意图(来源:Narayanan et al. 2021

张量并行

模型并行和管道并行都会垂直拆分模型,而张量并行(Tensor Parallelism,TP)是将张量运算的计算水平划分到多个设备上。

以Transformer为例。Transformer架构主要由多层MLP和自注意力块组成。Megatron-LM(Shoeybi et al.2020)采用了一种简单的方法来并行计算层内MLP和自注意力。

MLP层包含GEMM(通用矩阵乘法)和非线性GeLU传输。如果按列拆分权重矩阵A,可以得到:

注意力块根据上述分区并行运行GEMM的 查询(Q)、键(K)和 权重(V),然后与另一个GEMM组合以生成头注意力结果。

图8:Megatron-LM中提出的关键Transformer组件的张量平行性说明。(来源:Shoeybi等人,2020年)

今年Narayanan等人将管道、张量和数据并行与新的管道调度策略相结合,提出了一种名为PTD-P的新方法。该方法不仅在设备上能够定位一组连续的层(“模型块”),该可以为每个wokers分配多个较小的连续层子集块(例如,设备1具有第1、2、9、10层;设备2具有第3、4、11、12层;每个具有两个模型块)

每个batch中,微批次的数量应精确除以wokers数量(mm)。如果每个worker有v个模型块,那么与GPipe调度相比,管道的“气泡”时间可以减少 v 倍。

图9:上图与PipeDream flush中的默认1F1B管道明细表相同;下图为交错的1F1B管线一览表(来源:Narayanan等人,202)

2

混合专家(MoE)

为了突破模型大小的限制,谷歌后来提出一种混合专家(MoE)方法,其核心理念是:综合学习,它假设多个弱学习者组合起来就会拥有一个强学习者。

在深度神经网络中,混合专家(MoE)通过连接多个专家的门机制(gating mechanism)实现集成(Shazeer等人,2017)。门机制激活不同网络的专家以产生不同的输出。作者在论文将其命名为“稀疏门控专家混合层(sparsely gated MoE)”。

仅一个MoE层包含:(1)前馈网络专家n;(2)可训练的门控网络G,通过学习n个专家的概率分布,将流量路由到几个特定的专家。

根据门控输出,并非每个专家都必须进行评估。当专家的数量太大时,可以考虑使用两层MoE。

G将输入与可训练权重矩阵Gg相乘,然后执行softmax:

由于这个过程会产生密集的门控制向量,不利于节省计算资源,而且时也不需要评估专家。所以,MoE层仅保留了顶部k值,并通过向G中添加高斯噪声改进负载平衡,这种机制被称为噪声top-k门。

为了避免门控网络可能始终偏向少数强势专家的自我强化效应,Shazeer等人(2017)提出了通过额外重要损失的软约束,以鼓励所有专家拥有相同的权重。 其数值相当于每个专家的分批平均值变异系数的平方:

其中,CV是变异系数,失重的waux是可调节的超参数。由于每个专家网络只能获得小部分训练样本(“收缩批次问题”),所以在MoE中应该尽可能使用大batch,但这又会受到GPU内存的限制。数据并行和模型并行的应用可以提高模型的吞吐量。

图11:10亿单词的语言建模基准(左)模型从左到右包含4、32、256、256、1024和4096名专家(右)40亿参数的MoE模型在不同计算预算下的性能(来源:Shazeer等人,2017年)

GShard(Lepikhin等人,2020年)通过自动分片将MoE transformer 模型的参数扩展到了6000亿。MoE transformer 用MoE层取代其他每一个前馈网络层。需要说明的是,在多台机器上MoE transformer 仅在MoE层分片,其他层只是复制。

GShard中的门控功能G有几种改进设计:

  • 专家容量:通过一位专家的令牌数量不应超过“专家容量”的阈值。如果令牌被路由到已达到容量的专家,则令牌将被标记为“溢出”,并且门输出将更改为零向量。

  • 本地组调度:令牌被均匀地划分为多个本地组,专家能力在组水平上得到加强。

  • 辅助损失:与原始MoE aux损失相似,添加辅助损失可以最小化路由到每个专家的数据的均方。

  • 随机路由:以与其权重成比例的概率选择第二位最佳专家;否则GShard遵循随机路由,增加随机性。

图12:GShard中带辅助损失的组水平top-2门机制的伪代码(来源:Lepikhin等人,2020年)

Switch Transformer(Fedus et al.2021)用稀疏开关FFN层取代了密集前馈层(每个输入仅路由到一个专家网络),将模型规模扩展到数万亿个参数。负载平衡的辅助损失是,给定n个专家,fi是路由到第i个专家的令牌分数,pi是门控网络预测的专家i的路由概率。

为提高训练稳定性,switch transformer采用以下设计:

  • 选择精度:使用FP32精度以提高模型局部的稳定性,并降低FP32张量的通信成本。FP32精度仅在路由器功能主体内使用,结果将还原到FP16。 较小的初始化:权重矩阵的初始化从平均μ=0且标准偏差的正态分布中采样,同时将Transformer初始化参数从s=1减小到s=0.1 。

  • 使用更高的专家辍学率:微调通常适用于小数据集,增加每个专家的辍学率以避免过度拟合。他们发现,所有层中的辍学率增加会导致性能下降。在论文中,他们在非专家层中使用了0.1的辍学率,但在专家FF层中使用了0.4的辍学率。

switch transformer论文总结了用于训练大型模型的不同数据和模型并行策略,并给出了一个很好的示例:

3

其他节省内存的设计

CPU卸载

如果GPU内存已满,可以将暂时未使用的数据卸载到CPU,并在以后需要时将其读回(Rhu等人,2016)。不过,这种方法近年来并不太流行,因为它会延长模型训练的时间。

激活重新计算

激活重新计算,也称“激活检查点”或“梯度检查点”(Chen et al,2016),其核心思路是牺牲计算时间来换取内存空间。它减少了训练 ℓ 层深层神经网络到的内存开销,每个batch只消耗额外的前向传递计算。

具体来说,该方法将ℓ层网络平均划分为d个分区,仅保存分区边界的激活,并在workers之间进行通信。计算梯度仍然需要在分区内层进行中间激活,以便在向后过程中重新计算梯度。在激活重新计算的情况下,用于训练M(ℓ) 是:

它的最低成本是:

激活重新计算的方法可以得出与模型大小有关次线性内存开销,如下图:

混合精度训练

此前,Narang(Narang&Micikevicius等人,2018年)介绍了一种使用半精度浮点(FP16)数训练模型而不损失模型精度的方法。

其中涉及三种关键技术:

  • 全精度权重复制:保持累积梯度的模型权重的全精度(FP32)复制。对于向前和向后的传递的信息做四舍五入至半精度处理,因为每次梯度更新(即梯度X学习率)太小,可能无法完全包含在FP16范围内。

  • 缩放损失:放大损失以更好地处理小幅度的梯度(见图16),放大梯度以使其向可表示范围的右侧部分(包含较大的值)移动,从而保留可能丢失的值。

  • 算术精度:对于常见的网络算法(如矢量点积、矢量元素求和归约),将部分结果累加到FP32中,然后输出保存为FP16。逐点操作可以在FP16或FP32中执行。

图17::全精确的梯度直方图

在这项实验中,图像分类、更快的R-CNN等不需要损失缩放,但其他网络,如多盒SSD、大LSTM语言模型是需要损失缩放的。

压缩(Compression)

模型权重在向前和向后传递的过程中会消耗大量内存。考虑到这两种传递方式会花费大量时间,2018年Jain (Jain et al,2018)提出了一种数据编码策略,即在第一次传递后压缩中间结果,然后将其解码用于反向传播。

Jain和团队研发的Gist系统包含两种编码方案:一是特定于层的无损编码,包括 ReLU-Pool和 ReLU-Conv模式;二是有攻击性的有损编码,主要使用延迟精度缩减(DPR)。需要注意的是,第一次使用特征图时应保持高精度,第二次使用时要适度降低精度。这项实验表明,Gist可以在5个最佳图像分类DNN上减少2倍的内存开销,平均减少1.8倍,性能开销仅为4%。

内存高效优化器

优化器也会消耗内存。以主流的Adam优化器为例,其内部需要维护动量和方差,这两者与梯度和模型参数比例基本相同。这意味着,我们需要节省4倍模型权重的内存。

为了减少内存消耗,学术界已经提出了几款主流优化器。与Adam相比,Adafactor(Shazeer et al.2018)优化器没有存储全部动量和变化,只跟踪移动平均数的每行和每列总和,然后根据这些总和估计二阶矩。

SM3(Anil et al.2019)优化器采用了一种不同的自适应优化方法。

ZeRO(Rajbhandari et al.2019)零冗余优化器节省了大型模型训练在两方面的内存消耗:

  • 大多数内存由模型状态消耗,包括优化器状态(例如Adam动量和方差)、梯度和参数。混合精度训练也需要大量内存,因为除了FP16版本之外,优化器还需要保存FP32参数和其他优化器状态的副本。

  • 未被激活、临时缓冲区以及不可用的碎片内存消耗(论文中称为剩余状态)。

ZeRO结合了ZeRO-DP和ZeRO-R两种方法。ZeRO-DP是一种增强的数据并行,避免了模型状态的简单冗余。它以动态的方式跨多个并行数据划分优化器状态、梯度和参数,以最小化通信量。ZeRO-R使用分区激活二次计算、恒定缓冲区大小和动态内存碎片,以优化剩余状态的内存消耗。

参考资料:

[1] Li et al. “PyTorch Distributed: Experiences on Accelerating Data Parallel Training” VLDB 2020.

[2] Cui et al. “GeePS: Scalable deep learning on distributed GPUs with a GPU-specialized parameter server” EuroSys 2016

[3] Shoeybi et al. “Megatron-LM: Training Multi-Billion Parameter Language Models Using Model Parallelism.” arXiv preprint arXiv:1909.08053 (2019).

[4] Narayanan et al. “Efficient Large-Scale Language Model Training on GPU Clusters Using Megatron-LM.” arXiv preprint arXiv:2104.04473 (2021).

[5] Huang et al. “GPipe: Efficient Training of Giant Neural Networks using Pipeline Parallelism.” arXiv preprint arXiv:1811.06965 (2018).

[6] Narayanan et al. “PipeDream: Generalized Pipeline Parallelism for DNN Training.” SOSP 2019.

[7] Narayanan et al. “Memory-Efficient Pipeline-Parallel DNN Training.” ICML 2021.

[8] Shazeer et al. “The Sparsely-Gated Mixture-of-Experts Layer Noam.” arXiv preprint arXiv:1701.06538 (2017).

[9] Lepikhin et al. “GShard: Scaling Giant Models with Conditional Computation and Automatic Sharding.” arXiv preprint arXiv:2006.16668 (2020).

[10] Fedus et al. “Switch Transformers: Scaling to Trillion Parameter Models with Simple and Efficient Sparsity.” arXiv preprint arXiv:2101.03961 (2021).

[11] Narang & Micikevicius, et al. “Mixed precision training.” ICLR 2018.

[12] Chen et al. 2016 “Training Deep Nets with Sublinear Memory Cost.” arXiv preprint arXiv:1604.06174 (2016).

[13] Jain et al. “Gist: Efficient data encoding for deep neural network training.” ISCA 2018.

[14] Shazeer & Stern. “Adafactor: Adaptive learning rates with sublinear memory cost.” arXiv preprint arXiv:1804.04235 (2018).

[15] Anil et al. “Memory-Efficient Adaptive Optimization.” arXiv preprint arXiv:1901.11150 (2019).

[16] Rajbhandari et al. “ZeRO: Memory Optimization Towards Training A Trillion Parameter Models Samyam.” arXiv preprint arXiv:1910.02054 (2019).

编译链接:https://lilianweng.github.io/lil-log/2021/09/24/train-large-neural-networks.html

特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相关推荐
热点推荐
先炸西方督战队!俄军改变战术,效果立竿见影!

先炸西方督战队!俄军改变战术,效果立竿见影!

星辰故事屋
2024-11-29 11:27:15
齐秦大哥,如果不缺钱,就不要出来演唱了,这不好吗?

齐秦大哥,如果不缺钱,就不要出来演唱了,这不好吗?

阿尢说历史
2024-11-29 10:23:55
机器人概念完整解读,人工智能与人形机器人的深度契合将引领未来

机器人概念完整解读,人工智能与人形机器人的深度契合将引领未来

小佩棋不蹦迪
2024-11-29 18:07:48
“不违反规定”留双核,上港拿出最大诚意!巴尔加斯续约前景明朗

“不违反规定”留双核,上港拿出最大诚意!巴尔加斯续约前景明朗

中国足球的那些事儿
2024-11-29 18:20:58
担心被中国利用?加拿大财长这么回应

担心被中国利用?加拿大财长这么回应

观察者网
2024-11-30 10:08:59
太突然!厦门泉州全部闭店!有人充了好几万……

太突然!厦门泉州全部闭店!有人充了好几万……

业翔民安
2024-11-29 09:03:57
解救女孩司机获永久免除挂靠管理费,网友:好人有好报

解救女孩司机获永久免除挂靠管理费,网友:好人有好报

大象新闻
2024-11-30 08:52:54
女朋友腿粗,男生有多幸福??

女朋友腿粗,男生有多幸福??

健身S叔
2024-11-30 12:05:10
新婚夜,我妻子要求我必须戴眼罩,因为她的身体只能给白月光看

新婚夜,我妻子要求我必须戴眼罩,因为她的身体只能给白月光看

喵呜好故事
2024-09-27 18:10:57
安徽最新人事!涉多名县处级干部

安徽最新人事!涉多名县处级干部

鲁中晨报
2024-11-30 10:40:04
国足1人不可再用,若想进入世界杯,必须离开国家队

国足1人不可再用,若想进入世界杯,必须离开国家队

体坛狗哥
2024-11-29 17:38:45
外媒:汇丰将退出中国的信用卡业务服务

外媒:汇丰将退出中国的信用卡业务服务

凤凰网财经plus
2024-11-29 15:12:07
当孩子不尊重你、不理你时,不必翻脸,只需“乌鸦定律”就够了

当孩子不尊重你、不理你时,不必翻脸,只需“乌鸦定律”就够了

新东方家庭教育
2024-11-29 10:03:53
和尚老了也可怜!山西77岁僧人,山洞苦修13年,没吃没喝崩溃落泪

和尚老了也可怜!山西77岁僧人,山洞苦修13年,没吃没喝崩溃落泪

青栀伊人
2024-10-30 16:08:32
特朗普马斯克共度感恩节!名流齐聚气氛热烈,马斯克却不在状态

特朗普马斯克共度感恩节!名流齐聚气氛热烈,马斯克却不在状态

晓徙历史
2024-11-30 09:24:40
这才是万斯的真面目

这才是万斯的真面目

蓝钻故事
2024-11-29 20:11:51
布伦森31分尼克斯险胜黄蜂,三球缺阵布兰登-米勒25中7

布伦森31分尼克斯险胜黄蜂,三球缺阵布兰登-米勒25中7

OnFire
2024-11-30 07:09:02
23场20球!皇马39岁旧将爆发,今夏无缘回归,老佛爷1亿签姆巴佩

23场20球!皇马39岁旧将爆发,今夏无缘回归,老佛爷1亿签姆巴佩

球场没跑道
2024-11-30 12:13:45
锁定3.46亿顶薪,有你7胜7负,没你4胜1负!潮水退去才知谁在裸泳

锁定3.46亿顶薪,有你7胜7负,没你4胜1负!潮水退去才知谁在裸泳

老梁体育漫谈
2024-11-30 03:50:16
达成协议!皇马即将正式签约7000万攻击手!意大利新7号同步加盟

达成协议!皇马即将正式签约7000万攻击手!意大利新7号同步加盟

头狼追球
2024-11-29 18:33:30
2024-11-30 12:48:49
AI科技评论
AI科技评论
点评学术,服务AI
6677文章数 20622关注度
往期回顾 全部

科技要闻

"AGI不是大杀器,是普通人每天在用的产品"

头条要闻

男子露下体尾随16岁女孩 货车司机相救获奖4000元

头条要闻

男子露下体尾随16岁女孩 货车司机相救获奖4000元

体育要闻

穆雷与德约科维奇能凑成王炸组合吗?

娱乐要闻

一夜爆火的丁真,不进娱乐圈他后悔吗

财经要闻

雪松爆雷前实控人张劲在香港抛售房产

汽车要闻

比亚迪方程豹豹8推送首次OTA 新增暴力模式

态度原创

健康
数码
时尚
本地
房产

花18万治疗阿尔茨海默病,值不值?

数码要闻

三季度电视出货量同比下降6.6%,大尺寸、Mini LED成未来增长关键力量

直播|| 今年冬天只想背这个包!

本地新闻

云游中国|来伦布夏果感受充满Passion的人生

房产要闻

大量甩地!114亿,4790亩!海南土地市场全面爆发!

无障碍浏览 进入关怀版