AI大模型Tokens高效消耗:系统架构与工程实践指南 1. 项目概述当“烧掉”16亿Tokens成为一个技术命题最近在AI开发者和技术爱好者的圈子里一个看似荒诞实则极具挑战性的问题被频繁讨论如果你手头有16亿个AI大模型的Tokens代币你该如何“快速”地用掉它们这听起来像是一个土豪的烦恼或者一个纯粹为了测试极限而生的脑洞。但作为一名长期混迹于AI应用开发一线的从业者我看到的远不止于此。这背后触及的是对大模型成本结构、资源利用率、压力测试方法论乃至创新应用场景的深度思考。“Tokens”是当前大语言模型LLM世界的硬通货无论是输入还是输出每一次调用都在消耗它。16亿Tokens以当前主流商业API的价格粗略估算其价值可能高达数十万甚至上百万人民币。因此“快速用掉”绝非字面意义上的浪费而是一个严肃的技术工程问题它考验的是你设计高吞吐、可持续负载任务的能力是对数据处理管道、并发控制、成本监控以及最终价值产出的一次综合压力测试。无论是为了完成一笔必须消耗的预算还是为了对自建或采购的模型服务进行极限承压评估亦或是探索海量计算资源下的新型应用可能这个命题都具有实实在在的工程价值。在接下来的内容里我将抛开那些浮于表面的玩笑式回答从系统架构师和实战派的角度拆解实现这一目标的多种核心路径、技术细节与避坑指南。我们会探讨如何构建一个能稳定“吞食”海量Tokens的自动化系统分析不同任务类型如长文本生成、批量推理、持续对话的效率差异并分享在设计和执行此类任务时必须警惕的陷阱。无论你是AI产品经理规划资源使用还是开发者需要进行压力测试抑或是技术负责人评估基础设施的极限这些从实战中总结的经验都能为你提供直接的参考。2. 核心思路拆解从“挥霍”到“系统性消耗”的思维转变面对“消耗16亿Tokens”这个目标新手可能会想到手动输入一部长篇小说或者让AI无限循环地写诗。这种思路效率低下且不可持续。我们必须将问题从“个人操作”升级为“系统工程”。核心思路在于设计一个或多个能够自动化、批量化、高并发执行的任务管道让Tokens的消耗如同流水线上的产品稳定且高速。2.1 任务类型的选择与效率评估并非所有AI任务都适合快速消耗Tokens。我们需要选择那些“Tokens吞吐量”高、易于自动化、且对结果质量不敏感或可接受一定噪声的任务。以下是几种高效的任务类型及其效率分析长文本生成与续写这是最直接的消耗方式。通过提供一个种子文本让模型不断生成后续内容。效率取决于模型的“最大输出Tokens”限制和生成速度。例如如果模型单次调用最多可输出4000个Tokens那么理论上需要40万次调用才能消耗完16亿。关键在于自动化循环调用和上下文管理。批量翻译与摘要准备一个超大规模的文本语料库如整个维基百科的文本子集、公开的图书库让模型进行批量翻译或摘要。这种任务输入和输出都消耗Tokens且可以高度并行化。效率瓶颈在于数据读取、任务分片和结果存储的I/O性能。代码生成与补全准备海量的代码片段例如从GitHub抓取的公开项目让模型为这些代码生成注释、补全下一行、或转换为另一种编程语言。这对于测试代码模型特别有效且生成的输出有时还能产生意外有用的副产品。链式或递归式任务设计复杂的AI Agent工作流让一个任务的输出成为另一个任务的输入形成链条。例如让AI分析一篇文章根据分析结果生成一个故事大纲再根据大纲写出一章小说接着对小说进行润色和批评如此循环。这种模式能产生更复杂的交互消耗Tokens的“深度”和“广度”都很可观。数据合成与增强利用大模型生成训练数据。例如给定一个分类体系的描述让模型生成海量的对应类别样本。这不仅能消耗Tokens其产出还可能用于后续的模型训练变消耗为投资。注意在选择任务时必须严格遵守内容安全与伦理底线。绝对禁止用于生成任何违规、有害、侵犯隐私或用于不正当竞争的内容。我们的目标是技术压力测试与资源利用探索所有生成内容应控制在公开、合法、无争议的领域内。2.2 系统架构设计要点要稳定、高效地运行这样一个“Tokens消耗机”需要一个健壮的后台系统。其核心组件包括任务调度器负责任务队列的管理、分发到不同的工作节点。需要考虑优先级、重试机制和负载均衡。工作节点执行实际调用AI API的单元。每个节点需要处理与AI服务的连接、认证、请求发送、响应解析、错误处理。速率限制与并发控制所有AI服务API都有严格的速率限制RPM, TPM。系统必须精细控制请求频率既要逼近上限以最大化吞吐又要避免触发限流导致任务失败或API密钥被封禁。状态管理与监控实时追踪已消耗的Tokens总量、消耗速率、费用估算、任务成功率、错误类型分布。这需要与AI服务提供的使用量统计API对接或自行从响应头中提取Tokens消耗数据。数据管道负责为任务提供输入数据如文本库、代码库并持久化任务的输出结果。这可能涉及大型数据库或分布式文件系统。一个简化的架构流程是任务调度器从“任务池”中取出一个任务单元例如“翻译以下1000字文章”分配给一个空闲的工作节点。工作节点调用AI API记录消耗的Tokens将结果存入“结果存储”并向调度器报告成功。监控面板实时汇总所有节点的数据。3. 实操方案一构建高吞吐的批量文本处理管道这是最经典、最可控的方案。我们将以“批量文本风格迁移”为例详细说明如何构建一个能持续消耗Tokens的自动化系统。假设任务是将大量新闻文章改写为莎士比亚戏剧的风格。3.1 技术栈与工具选型编程语言Python是首选因其在AI和数据处理生态上的绝对优势。异步编程框架asyncio或aiohttp对于高并发API调用至关重要。AI服务选择提供清晰Tokens计数、稳定且速率限制较高的API。例如OpenAI的Chat Completions API、Anthropic的Claude API或国内主流大模型平台。关键点必须仔细阅读其API文档中关于Tokens计算和速率限制的部分。任务队列对于大规模任务使用CeleryRedis/RabbitMQ是成熟方案。对于轻量级或原型可以直接使用concurrent.futures线程池/进程池。数据存储输入文本可以存储在SQLite小规模、PostgreSQL或直接放在对象存储如S3、MinIO中。输出结果建议按任务ID和批次存储为JSONL文件便于后续处理和分析。监控使用PrometheusGrafana自定义指标或简单地将日志消耗量、时间戳、状态输出到文件再用脚本实时分析。3.2 核心实现步骤与代码要点步骤1准备语料库你需要一个足够大的文本源。可以是从Common Crawl、维基百科转储或Project Gutenberg中清洗和抽取出的纯文本文件。将文本切割成大小合适的片段例如每段1000-3000字并存储到数据库或文件列表中。假设我们准备了100万条文本片段。步骤2设计Prompt与API调用函数Prompt的设计直接影响输出长度和Tokens消耗。为了最大化输出可以设计鼓励长篇幅、细节描写的Prompt。import openai import asyncio import aiohttp from tenacity import retry, stop_after_attempt, wait_exponential # 配置API密钥和客户端示例为OpenAI client openai.AsyncOpenAI(api_keyyour-api-key) retry(stopstop_after_attempt(3), waitwait_exponential(multiplier1, min4, max10)) async def rewrite_text(session, text_chunk, prompt_template): 调用API重写文本片段 full_prompt prompt_template.format(texttext_chunk) try: response await client.chat.completions.create( modelgpt-4, # 或任何其他模型 messages[ {role: system, content: 你是一位莎士比亚风格的戏剧作家。}, {role: user, content: full_prompt} ], max_tokens2000, # 设置较大的输出限制以消耗更多Tokens temperature0.8, # 一定的随机性使输出更丰富 ) # 计算本次调用消耗的Tokens输入输出 input_tokens response.usage.prompt_tokens output_tokens response.usage.completion_tokens total_tokens response.usage.total_tokens rewritten_text response.choices[0].message.content return { original_text: text_chunk, rewritten_text: rewritten_text, input_tokens: input_tokens, output_tokens: output_tokens, total_tokens: total_tokens } except Exception as e: # 记录错误重试机制由tenacity处理 print(fError processing chunk: {e}) raise # Prompt模板示例 PROMPT_TEMPLATE 请将以下现代新闻文本用威廉·莎士比亚戏剧的古典英文风格进行重写要求尽可能保留原意但使用戏剧化的对白、比喻和五步抑扬格的诗句风格。请充分发挥让改写后的文本足够长且富有文学性。 原文 {text} 莎士比亚风格改写 步骤3实现异步批量处理器这是系统的核心负责控制并发、处理限流和收集结果。import aiofiles import json import time from collections import deque class TokenConsumer: def __init__(self, api_client, rate_limit_per_minute10000): self.client api_client self.rate_limit rate_limit_per_minute self.semaphore asyncio.Semaphore(50) # 控制最大并发连接数 self.request_times deque(maxlenrate_limit) # 用于滑动窗口限流 self.total_tokens_consumed 0 async def _rate_limiter(self): 简单的令牌桶算法实现速率限制 now time.time() # 移除一分钟以前的请求记录 while self.request_times and now - self.request_times[0] 60: self.request_times.popleft() if len(self.request_times) self.rate_limit: # 计算需要等待的时间 sleep_time 60 - (now - self.request_times[0]) if sleep_time 0: await asyncio.sleep(sleep_time) self.request_times.append(time.time()) async def process_batch(self, text_chunks, output_fileresults.jsonl): 处理一批文本 tasks [] async with aiofiles.open(output_file, a) as f: for chunk in text_chunks: async with self.semaphore: await self._rate_limiter() # 遵守速率限制 task asyncio.create_task( self._process_single(chunk, f) ) tasks.append(task) # 等待所有任务完成 results await asyncio.gather(*tasks, return_exceptionsTrue) # 处理结果和异常 successful [r for r in results if not isinstance(r, Exception)] failed [r for r in results if isinstance(r, Exception)] print(fBatch completed. Successful: {len(successful)}, Failed: {len(failed)}) return self.total_tokens_consumed async def _process_single(self, text_chunk, output_file_handle): 处理单个文本块并写入文件 try: result await rewrite_text(self.client, text_chunk, PROMPT_TEMPLATE) self.total_tokens_consumed result[total_tokens] # 异步写入结果 await output_file_handle.write(json.dumps(result, ensure_asciiFalse) \n) # 定期打印进度 if self.total_tokens_consumed % 100000 1000: # 每消耗约10万Tokens打印一次 print(fTotal tokens consumed so far: {self.total_tokens_consumed:,}) return result except Exception as e: print(fFailed to process chunk: {e}) return e # 主函数 async def main(): # 假设 load_text_chunks 函数从你的数据源加载文本 all_chunks load_text_chunks(limit1000000) # 加载100万个片段 consumer TokenConsumer(api_client, rate_limit_per_minute90000) # 根据API实际限制设置 batch_size 1000 for i in range(0, len(all_chunks), batch_size): batch all_chunks[i:ibatch_size] tokens await consumer.process_batch(batch, output_filefresults_batch_{i//batch_size}.jsonl) print(fFinished batch {i//batch_size}, cumulative tokens: {tokens:,}) if __name__ __main__: asyncio.run(main())3.3 关键参数调优与成本估算并发数与速率限制这是效率的核心。rate_limit_per_minute必须设置为略低于API官方限制如官方限制10万TPM可设9万。Semaphore的值并发连接数需要根据网络延迟和服务器性能调整通常从20开始测试逐步增加观察错误率。max_tokens参数这是控制单次输出Tokens量的直接杠杆。设置得越高单次调用消耗Tokens越多但生成时间也越长且可能因内容不相关导致浪费。需要根据任务和模型上下文长度权衡。对于“风格改写”任务设为2000-4000是合理的。成本估算假设使用GPT-4 Turbo模型输入输出混合单价约为$10 / 1M Tokens。16亿Tokens ≈ 1.6M (Million) Tokens * 10 $16,000。这是一个不小的数字凸显了成本监控的重要性。必须在代码中实时累计并预警。实操心得在正式大规模运行前务必用小批量如100条数据进行试跑。这不仅能测试管道稳定性还能估算出平均每条数据消耗的Tokens数从而更准确地预测总消耗进度和费用。例如试跑后算出平均每处理一个文本片段消耗1500个Tokens那么要消耗16亿大约需要处理106万个片段。4. 实操方案二设计复杂的AI Agent递归任务链如果觉得单纯的文本改写太枯燥且想探索更复杂的交互模式设计一个自驱动、递归的AI Agent系统是更高级的选择。这种方案消耗Tokens的“深度”极大因为一次交互可能引发多轮次、多模型的连续调用。4.1 任务链设计示例模拟一个“永不停歇的研究助理”我们设计一个Agent它能够自动提出研究问题、搜集信息模拟、进行分析、提出新问题如此循环。这个循环本身可以消耗大量Tokens并且能产生结构化的“思考”记录。Agent工作流程问题生成器基于一个初始主题如“量子计算对密码学的影响”生成一个具体的研究子问题。信息搜集器模拟搜索过程实际上可以调用联网搜索的API或从一个预设的知识库中检索相关段落。这一步的“模拟”本身也需要用模型生成一段模拟的检索结果摘要。分析器对“搜集到”的信息进行总结、分析并评估其与问题的相关性。综述与提问器基于分析撰写一段研究笔记并提出1-3个由此衍生的、更深入的新问题。循环控制将新问题作为下一轮的输入重复步骤1-4。可以设置停止条件如达到一定循环次数、问题深度或累计消耗Tokens目标。4.2 实现框架与状态管理这种链式系统比批量处理更复杂需要维护每个“研究线程”的状态。我们可以使用LangChain、LlamaIndex这类AI应用框架来简化编排但为了理解底层原理这里展示一个简化的自定义实现。import json from dataclasses import dataclass, asdict from typing import List, Optional dataclass class ResearchState: 记录单个研究线程的状态 thread_id: str original_topic: str current_question: str history: List[dict] # 记录每一轮的问答和分析 total_tokens_used: int 0 depth: int 0 class ResearchAgent: def __init__(self, api_client, max_depth10): self.client api_client self.max_depth max_depth async def run_thread(self, initial_topic: str, thread_id: str) - ResearchState: 运行一个研究线程 state ResearchState( thread_idthread_id, original_topicinitial_topic, current_questionf请围绕{initial_topic}提出一个具体、可研究的问题。, history[], total_tokens_used0, depth0 ) while state.depth self.max_depth: # 1. 生成/回答问题 (模拟信息搜集和分析) round_result await self._conduct_one_round(state) state.history.append(round_result) state.total_tokens_used round_result[tokens_used] state.depth 1 # 2. 生成新问题 new_question await self._generate_new_question(state) state.current_question new_question # 打印进度 print(fThread {thread_id} - Depth {state.depth}: Tokens{state.total_tokens_used:,}, Q{new_question[:50]}...) # 简单停止条件如果新问题与旧问题高度相似或空洞则停止 if self._should_stop(state): break return state async def _conduct_one_round(self, state: ResearchState) - dict: 执行单轮研究生成答案并分析 # 模拟信息搜集让AI扮演搜索引擎生成一段“找到”的信息 search_prompt f假设你是一个专业的学术搜索引擎。针对问题{state.current_question}请生成一段模拟的、信息丰富的摘要约300字包含关键事实、数据和观点。 search_response await self._call_llm(search_prompt, max_tokens500) simulated_info search_response[content] search_tokens search_response[tokens] # 分析信息让AI对上述模拟信息进行分析 analysis_prompt f基于以下模拟检索到的信息请对问题“{state.current_question}”进行深入分析。 信息 {simulated_info} 要求 1. 总结核心观点。 2. 指出信息中可能存在的矛盾或未解之处。 3. 评估该信息对回答原问题的贡献度。 请输出结构化的分析报告。 analysis_response await self._call_llm(analysis_prompt, max_tokens600) analysis_tokens analysis_response[tokens] total_tokens_round search_tokens analysis_tokens return { question: state.current_question, simulated_info: simulated_info, analysis: analysis_response[content], tokens_used: total_tokens_round } async def _generate_new_question(self, state: ResearchState) - str: 基于历史生成一个新的研究问题 history_summary \n.join([fQ{h[question]}\nA:{h[analysis][:100]}... for h in state.history[-3:]]) # 取最近三轮 prompt f你是一名不断深入探索的研究员。以下是近期的研究记录 {history_summary} 请提出一个由此自然衍生出的、更具体或更深入的新研究问题。问题应具有可探究性。 response await self._call_llm(prompt, max_tokens200) return response[content].strip() async def _call_llm(self, prompt: str, max_tokens: int) - dict: 通用的LLM调用封装返回内容和Tokens数 # 此处调用实际的API同方案一中的rewrite_text函数类似 # 为简洁省略具体实现返回模拟数据 # 实际应用中应包含错误重试、计费等逻辑 return {content: f模拟响应于: {prompt[:30]}..., tokens: max_tokens//2} # 模拟消耗一半的max_tokens def _should_stop(self, state: ResearchState) - bool: 简单的停止条件判断 if state.depth self.max_depth: return True if len(state.history) 1: last_q state.history[-1][question] current_q state.current_question # 如果问题重复或变得非常短则停止 if current_q in [h[question] for h in state.history] or len(current_q) 10: return True return False # 运行多个Agent线程以并行消耗Tokens async def run_agent_system(initial_topics: List[str]): agent ResearchAgent(api_clientNone) # 需传入真实client tasks [] for i, topic in enumerate(initial_topics): task asyncio.create_task(agent.run_thread(topic, fThread-{i})) tasks.append(task) all_states await asyncio.gather(*tasks) total_tokens sum(s.total_tokens_used for s in all_states) print(f所有研究线程完成。总计消耗Tokens: {total_tokens:,}) # 可以将所有state保存下来作为生成的“研究记录”4.3 方案优缺点与适用场景优点Tokens消耗效率高单次循环涉及多轮、多步骤的模型调用交互深度大。产出物可能有趣生成的“研究记录”本身可能包含一些有启发性的内容组合虽然是由模型虚构的。压力测试全面能测试模型在复杂、多轮对话场景下的稳定性、上下文管理能力和逻辑一致性。缺点系统复杂度高状态管理、循环逻辑、停止条件的设计都需要精心考虑调试更困难。不可预测性由于模型的随机性任务链可能陷入循环或产生无意义输出导致Tokens浪费在无效循环上。成本控制更难难以精确预测单次循环的Tokens消耗总预算控制需要更动态的监控。适用场景更适合用于测试AI Agent框架的极限性能或者在进行有明确探索目标如测试模型在特定领域的推理深度时附带完成Tokens消耗任务。5. 核心挑战与故障排查实录在实际操作中你会遇到一系列工程和业务层面的挑战。以下是我在类似项目中踩过的坑和总结的应对策略。5.1 API限制与稳定性问题这是最大的外部挑战。所有云服务商都会对API调用进行限流。问题现象请求频繁返回429 Too Many Requests错误或rate limit exceeded。排查与解决精细化速率控制不要简单使用sleep固定间隔。实现一个令牌桶或滑动窗口算法严格将请求速率控制在官方限制的80%-90%。上述代码中的_rate_limiter方法是一个简易滑动窗口实现。利用重试机制使用tenacity等库为请求添加指数退避重试。但要注意重试本身也会消耗时间可能影响整体吞吐。多地域/多API密钥轮询如果条件允许使用多个API密钥来自不同项目甚至多个服务商如同时调用OpenAI和Claude并设计负载均衡策略。这能极大提升总吞吐上限。监控与自适应实时监控错误率。当错误率上升时自动调低并发数或请求速率。5.2 任务管理与状态恢复长时间运行的任务可能因网络波动、程序崩溃或API临时故障而中断。问题现象程序崩溃后重启不知道哪些任务已经处理哪些还没处理可能导致重复处理或数据丢失。排查与解决实现任务幂等性给每个待处理的数据单元分配唯一ID如MD5值。在处理前先检查结果存储中是否已存在该ID的结果。如果存在则跳过。使用持久化任务队列如Celery配合Redis作为Broker任务状态会被持久化。即使Worker崩溃任务也会重新入队。定期检查点在批量处理中每完成一个批次如每1000条就将已处理的数据ID列表和累计Tokens数保存到一个检查点文件。重启时从检查点加载跳过已处理的数据。5.3 输出质量与内容安全风险在追求Tokens消耗速度时很容易忽略输出内容的质量和安全。问题现象生成的内容大量重复、毫无意义如“哈哈哈哈”循环或偶然触发生成不合规内容导致API调用被警告甚至封禁。排查与解决设置内容过滤器在将Prompt发送给大模型前可以先用一个简单的规则或小模型对输入进行筛查过滤掉明显无意义或高风险的种子文本。后处理与抽样检查定期如每消耗1000万Tokens抽样检查生成的内容。如果发现质量严重下降需要调整Prompt或任务设计。例如在风格改写任务中如果发现输出开始大量重复可以在Prompt中加入“请确保每次改写都有独特的措辞和比喻”。使用API的内容安全功能大多数商业API都内置了内容安全层。确保启用这些功能它们能拦截大部分明显违规的请求或响应保护你的账户。5.4 成本监控与预算告警这是一个财务问题但技术上必须实现。问题现象任务运行一夜后发现费用远超预算或者Tokens消耗速度远低于预期。排查与解决实时计量与上报代码中必须像前文示例一样累加每次调用的usage.total_tokens。并定期如每分钟将累计值推送到监控系统如Prometheus或写入日志。设置预算阈值告警在监控系统中设置告警规则。例如“当预估费用达到预算的50%时”发送邮件或短信告警。“当过去一小时的Tokens消耗速率低于预期值的50%时”告警这可能意味着任务卡住了。预估完成时间根据当前平均消耗速率和剩余Tokens动态计算预计完成时间并在仪表盘上显示。6. 效率优化与高级策略当基本管道跑通后可以进一步优化向“更快、更稳、更省”的目标迈进。6.1 模型与参数调优选择性价比更高的模型如果对生成质量要求不高纯粹为了消耗Tokens可以选择更便宜、速度更快的模型。例如从gpt-4切换到gpt-3.5-turbo成本可能降至1/10甚至1/20吞吐量也能大幅提升。调整生成参数temperature较高的温度如0.9-1.2会增加输出的随机性和多样性可能使生成内容更长、更丰富从而消耗更多Tokens。但过高也可能导致语法混乱。presence_penalty/frequency_penalty适当调高这些参数可以抑制重复用词鼓励模型使用更多不同的词汇可能间接增加输出长度。max_tokens这是最直接的杠杆。但需注意不要设得超过模型上下文限制且过大的值可能导致生成大量无关的“废话”。6.2 系统级优化异步I/O与连接池确保使用aiohttp等异步HTTP客户端并复用连接池避免为每个请求创建新连接的开销。批量请求如果API支持少数API支持批量请求即一次调用发送多个独立的消息返回多个独立的补全。这可以显著减少网络往返开销。如果可用应优先采用。地理亲和性如果你的服务器和AI服务的服务器在同一个地理区域例如都在美东网络延迟会更低整体吞吐更高。分离计算与I/O将耗时的结果处理如解析、写入数据库与API调用放在不同的线程或进程中进行避免阻塞主请求循环。6.3 混合任务策略不要只依赖单一任务类型。可以设计一个“任务混合器”随机或按比例选择不同的任务类型如30%长文本生成、30%翻译、20%代码生成、20%问答来执行。这样做有两大好处避免模型“疲劳”单一任务可能导致模型输出模式僵化混合任务能保持请求分布的多样性更贴近真实场景的压力测试。探索消耗瓶颈可以发现哪种任务在单位时间内消耗Tokens的效率最高从而动态调整任务混合比例实现全局最优。7. 伦理、合规与价值反思在疯狂“消耗”的背后我们必须保持清醒。这不仅仅是一个技术游戏。资源伦理电力、算力是真实的能源消耗。我们的测试应当有其目的或是为了优化未来的应用效率或是为了进行必要的压力测试。纯粹为了消耗而消耗的行为不值得提倡。数据合规使用的输入语料必须是合法、公开、无版权争议的。生成的内容也应妥善处理避免泄露或用于不当用途。价值锚点在项目设计之初就要问自己消耗完这些Tokens后我们得到了什么是一个经过极限测试的稳定系统架构是一批可用于数据增强的合成数据还是对模型能力边界的一次深刻认知让这个过程产生附加价值而不仅仅是数字的增长。最后分享一个我在某次大规模压力测试后的小技巧在长时间运行此类任务时除了监控Tokens和费用一定要监控你的工作节点和服务器的内存、CPU使用率。我曾遇到过因为结果数据在内存中堆积未及时写入磁盘导致程序内存溢出崩溃的情况。一个简单的解决方案是使用异步队列将结果写入操作也异步化并设置一个缓冲区大小当缓冲区满时暂停处理等待写入完成。技术细节的魔鬼往往藏在海量数据的长跑中。