[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"similar-Santosh-Gupta--SpeedTorch":3,"tool-Santosh-Gupta--SpeedTorch":61},[4,18,26,36,44,53],{"id":5,"name":6,"github_repo":7,"description_zh":8,"stars":9,"difficulty_score":10,"last_commit_at":11,"category_tags":12,"status":17},4358,"openclaw","openclaw\u002Fopenclaw","OpenClaw 是一款专为个人打造的本地化 AI 助手，旨在让你在自己的设备上拥有完全可控的智能伙伴。它打破了传统 AI 助手局限于特定网页或应用的束缚，能够直接接入你日常使用的各类通讯渠道，包括微信、WhatsApp、Telegram、Discord、iMessage 等数十种平台。无论你在哪个聊天软件中发送消息，OpenClaw 都能即时响应，甚至支持在 macOS、iOS 和 Android 设备上进行语音交互，并提供实时的画布渲染功能供你操控。\n\n这款工具主要解决了用户对数据隐私、响应速度以及“始终在线”体验的需求。通过将 AI 部署在本地，用户无需依赖云端服务即可享受快速、私密的智能辅助，真正实现了“你的数据，你做主”。其独特的技术亮点在于强大的网关架构，将控制平面与核心助手分离，确保跨平台通信的流畅性与扩展性。\n\nOpenClaw 非常适合希望构建个性化工作流的技术爱好者、开发者，以及注重隐私保护且不愿被单一生态绑定的普通用户。只要具备基础的终端操作能力（支持 macOS、Linux 及 Windows WSL2），即可通过简单的命令行引导完成部署。如果你渴望拥有一个懂你",349277,3,"2026-04-06T06:32:30",[13,14,15,16],"Agent","开发框架","图像","数据工具","ready",{"id":19,"name":20,"github_repo":21,"description_zh":22,"stars":23,"difficulty_score":10,"last_commit_at":24,"category_tags":25,"status":17},3808,"stable-diffusion-webui","AUTOMATIC1111\u002Fstable-diffusion-webui","stable-diffusion-webui 是一个基于 Gradio 构建的网页版操作界面，旨在让用户能够轻松地在本地运行和使用强大的 Stable Diffusion 图像生成模型。它解决了原始模型依赖命令行、操作门槛高且功能分散的痛点，将复杂的 AI 绘图流程整合进一个直观易用的图形化平台。\n\n无论是希望快速上手的普通创作者、需要精细控制画面细节的设计师，还是想要深入探索模型潜力的开发者与研究人员，都能从中获益。其核心亮点在于极高的功能丰富度：不仅支持文生图、图生图、局部重绘（Inpainting）和外绘（Outpainting）等基础模式，还独创了注意力机制调整、提示词矩阵、负向提示词以及“高清修复”等高级功能。此外，它内置了 GFPGAN 和 CodeFormer 等人脸修复工具，支持多种神经网络放大算法，并允许用户通过插件系统无限扩展能力。即使是显存有限的设备，stable-diffusion-webui 也提供了相应的优化选项，让高质量的 AI 艺术创作变得触手可及。",162132,"2026-04-05T11:01:52",[14,15,13],{"id":27,"name":28,"github_repo":29,"description_zh":30,"stars":31,"difficulty_score":32,"last_commit_at":33,"category_tags":34,"status":17},1381,"everything-claude-code","affaan-m\u002Feverything-claude-code","everything-claude-code 是一套专为 AI 编程助手（如 Claude Code、Codex、Cursor 等）打造的高性能优化系统。它不仅仅是一组配置文件，而是一个经过长期实战打磨的完整框架，旨在解决 AI 代理在实际开发中面临的效率低下、记忆丢失、安全隐患及缺乏持续学习能力等核心痛点。\n\n通过引入技能模块化、直觉增强、记忆持久化机制以及内置的安全扫描功能，everything-claude-code 能显著提升 AI 在复杂任务中的表现，帮助开发者构建更稳定、更智能的生产级 AI 代理。其独特的“研究优先”开发理念和针对 Token 消耗的优化策略，使得模型响应更快、成本更低，同时有效防御潜在的攻击向量。\n\n这套工具特别适合软件开发者、AI 研究人员以及希望深度定制 AI 工作流的技术团队使用。无论您是在构建大型代码库，还是需要 AI 协助进行安全审计与自动化测试，everything-claude-code 都能提供强大的底层支持。作为一个曾荣获 Anthropic 黑客大奖的开源项目，它融合了多语言支持与丰富的实战钩子（hooks），让 AI 真正成长为懂上",148568,2,"2026-04-09T23:34:24",[14,13,35],"语言模型",{"id":37,"name":38,"github_repo":39,"description_zh":40,"stars":41,"difficulty_score":32,"last_commit_at":42,"category_tags":43,"status":17},2271,"ComfyUI","Comfy-Org\u002FComfyUI","ComfyUI 是一款功能强大且高度模块化的视觉 AI 引擎，专为设计和执行复杂的 Stable Diffusion 图像生成流程而打造。它摒弃了传统的代码编写模式，采用直观的节点式流程图界面，让用户通过连接不同的功能模块即可构建个性化的生成管线。\n\n这一设计巧妙解决了高级 AI 绘图工作流配置复杂、灵活性不足的痛点。用户无需具备编程背景，也能自由组合模型、调整参数并实时预览效果，轻松实现从基础文生图到多步骤高清修复等各类复杂任务。ComfyUI 拥有极佳的兼容性，不仅支持 Windows、macOS 和 Linux 全平台，还广泛适配 NVIDIA、AMD、Intel 及苹果 Silicon 等多种硬件架构，并率先支持 SDXL、Flux、SD3 等前沿模型。\n\n无论是希望深入探索算法潜力的研究人员和开发者，还是追求极致创作自由度的设计师与资深 AI 绘画爱好者，ComfyUI 都能提供强大的支持。其独特的模块化架构允许社区不断扩展新功能，使其成为当前最灵活、生态最丰富的开源扩散模型工具之一，帮助用户将创意高效转化为现实。",108111,"2026-04-08T11:23:26",[14,15,13],{"id":45,"name":46,"github_repo":47,"description_zh":48,"stars":49,"difficulty_score":32,"last_commit_at":50,"category_tags":51,"status":17},6121,"gemini-cli","google-gemini\u002Fgemini-cli","gemini-cli 是一款由谷歌推出的开源 AI 命令行工具，它将强大的 Gemini 大模型能力直接集成到用户的终端环境中。对于习惯在命令行工作的开发者而言，它提供了一条从输入提示词到获取模型响应的最短路径，无需切换窗口即可享受智能辅助。\n\n这款工具主要解决了开发过程中频繁上下文切换的痛点，让用户能在熟悉的终端界面内直接完成代码理解、生成、调试以及自动化运维任务。无论是查询大型代码库、根据草图生成应用，还是执行复杂的 Git 操作，gemini-cli 都能通过自然语言指令高效处理。\n\n它特别适合广大软件工程师、DevOps 人员及技术研究人员使用。其核心亮点包括支持高达 100 万 token 的超长上下文窗口，具备出色的逻辑推理能力；内置 Google 搜索、文件操作及 Shell 命令执行等实用工具；更独特的是，它支持 MCP（模型上下文协议），允许用户灵活扩展自定义集成，连接如图像生成等外部能力。此外，个人谷歌账号即可享受免费的额度支持，且项目基于 Apache 2.0 协议完全开源，是提升终端工作效率的理想助手。",100752,"2026-04-10T01:20:03",[52,13,15,14],"插件",{"id":54,"name":55,"github_repo":56,"description_zh":57,"stars":58,"difficulty_score":32,"last_commit_at":59,"category_tags":60,"status":17},4721,"markitdown","microsoft\u002Fmarkitdown","MarkItDown 是一款由微软 AutoGen 团队打造的轻量级 Python 工具，专为将各类文件高效转换为 Markdown 格式而设计。它支持 PDF、Word、Excel、PPT、图片（含 OCR）、音频（含语音转录）、HTML 乃至 YouTube 链接等多种格式的解析，能够精准提取文档中的标题、列表、表格和链接等关键结构信息。\n\n在人工智能应用日益普及的今天，大语言模型（LLM）虽擅长处理文本，却难以直接读取复杂的二进制办公文档。MarkItDown 恰好解决了这一痛点，它将非结构化或半结构化的文件转化为模型“原生理解”且 Token 效率极高的 Markdown 格式，成为连接本地文件与 AI 分析 pipeline 的理想桥梁。此外，它还提供了 MCP（模型上下文协议）服务器，可无缝集成到 Claude Desktop 等 LLM 应用中。\n\n这款工具特别适合开发者、数据科学家及 AI 研究人员使用，尤其是那些需要构建文档检索增强生成（RAG）系统、进行批量文本分析或希望让 AI 助手直接“阅读”本地文件的用户。虽然生成的内容也具备一定可读性，但其核心优势在于为机器",93400,"2026-04-06T19:52:38",[52,14],{"id":62,"github_repo":63,"name":64,"description_en":65,"description_zh":66,"ai_summary_zh":67,"readme_en":68,"readme_zh":69,"quickstart_zh":70,"use_case_zh":71,"hero_image_url":72,"owner_login":73,"owner_name":74,"owner_avatar_url":75,"owner_bio":76,"owner_company":77,"owner_location":78,"owner_email":79,"owner_twitter":77,"owner_website":77,"owner_url":80,"languages":81,"stars":86,"forks":87,"last_commit_at":88,"license":89,"difficulty_score":10,"env_os":90,"env_gpu":91,"env_ram":92,"env_deps":93,"category_tags":98,"github_topics":99,"view_count":32,"oss_zip_url":77,"oss_zip_packed_at":77,"status":17,"created_at":119,"updated_at":120,"faqs":121,"releases":136},6115,"Santosh-Gupta\u002FSpeedTorch","SpeedTorch","Library for faster pinned CPU \u003C-> GPU transfer in Pytorch ","SpeedTorch 是一款专为 PyTorch 设计的开源加速库，旨在显著提升 CPU 与 GPU 之间的数据传输效率。在深度学习训练中，尤其是处理大规模稀疏嵌入（Embeddings）时，显存往往成为瓶颈，而传统的数据传输方式又较为缓慢。SpeedTorch 通过利用固定在内存中的 Cupy 张量技术，实现了比原生 PyTorch 快 3.1 倍的 CPU 到 GPU 传输速度，以及在特定场景下高达 410 倍的反向传输速度。\n\n这一工具主要解决了大模型训练中显存不足和数据加载延迟的问题。它允许开发者将闲置的参数存储在容量更大的 CPU 内存中，仅在计算需要时快速调入 GPU，从而突破显存限制。此外，得益于高效的数据流转，用户现在可以使用 Adam、RMSprop 等更多样化的优化器来训练稀疏嵌入，而不必局限于少数几种支持稀疏梯度的传统算法。\n\nSpeedTorch 特别适合从事自然语言处理、推荐系统研发的 AI 工程师和研究人员，尤其是那些需要处理海量词汇表或特征嵌入的场景。其核心亮点在于透明的接口设计，提供了兼容的工厂类来灵活配置张量位置，让现有代码无需大幅重构即可享受性能红利","SpeedTorch 是一款专为 PyTorch 设计的开源加速库，旨在显著提升 CPU 与 GPU 之间的数据传输效率。在深度学习训练中，尤其是处理大规模稀疏嵌入（Embeddings）时，显存往往成为瓶颈，而传统的数据传输方式又较为缓慢。SpeedTorch 通过利用固定在内存中的 Cupy 张量技术，实现了比原生 PyTorch 快 3.1 倍的 CPU 到 GPU 传输速度，以及在特定场景下高达 410 倍的反向传输速度。\n\n这一工具主要解决了大模型训练中显存不足和数据加载延迟的问题。它允许开发者将闲置的参数存储在容量更大的 CPU 内存中，仅在计算需要时快速调入 GPU，从而突破显存限制。此外，得益于高效的数据流转，用户现在可以使用 Adam、RMSprop 等更多样化的优化器来训练稀疏嵌入，而不必局限于少数几种支持稀疏梯度的传统算法。\n\nSpeedTorch 特别适合从事自然语言处理、推荐系统研发的 AI 工程师和研究人员，尤其是那些需要处理海量词汇表或特征嵌入的场景。其核心亮点在于透明的接口设计，提供了兼容的工厂类来灵活配置张量位置，让现有代码无需大幅重构即可享受性能红利。如果你正在为显存捉襟见肘或数据管道阻塞而困扰，SpeedTorch 提供了一个轻量且高效的解决方案。","\u003Cp align=\"center\">\n  \u003Cimg src=\"https:\u002F\u002Fi.imgur.com\u002Fwr4VaUV.png?1\">\n\u003C\u002Fp>\n\n# SpeedTorch\n\n[![Join the chat at https:\u002F\u002Fgitter.im\u002FSpeedTorch\u002Fcommunity](https:\u002F\u002Fbadges.gitter.im\u002FSpeedTorch\u002Fcommunity.svg)](https:\u002F\u002Fgitter.im\u002FSpeedTorch\u002Fcommunity?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Downloads](https:\u002F\u002Foss.gittoolsai.com\u002Fimages\u002FSantosh-Gupta_SpeedTorch_readme_ec93fc81d569.png)](https:\u002F\u002Fpepy.tech\u002Fproject\u002Fspeedtorch) [![Downloads](https:\u002F\u002Foss.gittoolsai.com\u002Fimages\u002FSantosh-Gupta_SpeedTorch_readme_ec93fc81d569.png\u002Fweek)](https:\u002F\u002Fpepy.tech\u002Fproject\u002Fspeedtorch\u002Fweek)\n\nFaster pinned CPU tensor \u003C-> GPU Pytorch variabe transfer and GPU tensor \u003C-> GPU Pytorch variable transfer, in certain cases. \n\n## Update 9-29-19\n\nSince for some systems, using the pinned Pytorch CPU tensors is faster than using Cupy tensors (see 'How It Works' section for more detail), I created general Pytorch tensor classes `PytorchModelFactory` and `PytorchOptimizerFactory` which can specifiy either setting the tensors to `cuda` or `cpu`, and if using `cpu`, if its memory should be pinned. The original `GPUPytorchModelFactory` and `GPUPytorchOptimizerFactory` classes are still in the library, so no existing code using SpeedTorch should be affected. The documentation has been updated to include these new classes. \n\n## What is it?\n\nThis library revovles around Cupy tensors pinned to CPU, which can achieve **3.1x** faster CPU -> GPU transfer than regular Pytorch Pinned CPU tensors can, and **410x** faster GPU -> CPU transfer. Speed depends on amount of data, and number of CPU cores on your system (see the How it Works section for more details)\n\nThe library includes functions for embeddings training; it can host embeddings on CPU RAM while they are idle, sparing GPU RAM. \n\n## Inspiration\n\nI initially created this library to help train large numbers of embeddings, which the GPU may have trouble holding in RAM. In order to do this, I found that by hosting some of the embeddings on the CPU can help achieve this. Embedding systems use sprase training; only fraction of the total prameters participate in the forward\u002Fupdate steps, the rest are idle. So I figured, why not keep the idle parameters off the GPU during the training step? For this, I needed fast CPU -> GPU transfer. \n\nFor the full backstory, please see the Devpost page\n\nhttps:\u002F\u002Fdevpost.com\u002Fsoftware\u002Fspeedtorch-6w5unb\n\n## What can fast CPU->GPU do for me? (more that you might initially think)\n\nWith fast CPU->GPU, a lot of fun methods can be developed for functionalities which previously people thought may not have been possible. \n\n🏎️    Incorporate SpeedTorch into your data pipelines for fast data transfer to\u002Ffrom CPU \u003C-> GPU\n\n🏎️    Augment training parameters via CPU storage. As long as you have enough CPU RAM, you can host any number of embeddings without having to worry about the GPU RAM.\n\n🏎️    Use Adadelta, Adamax, RMSprop, Rprop, ASGD, AdamW, and Adam optimizers for sparse embeddings training. Previously, only SpraseAdam, Adagrad, and SGD were suitable since only these directly support sparse gradients. \n\n\u003Cp align=\"center\">\n  \u003Cimg src=\"https:\u002F\u002Fi.imgur.com\u002F6o8C1BP.gif\">\n\u003C\u002Fp>\n\n## Benchmarks\n\n### Speed\n\n(Edit 9-20-19, one of the Pytorch developers pointed out some minor bugs in the original bench marking code, the values and code have been updated)\n\nHere is a notebook comparing transfer via SpeedTorch vs Pytorch tensors, with both pinned CPU and Cuda tensors. All tests were done with a colab instance with a Tesla K80 GPU, and 2 core CPU. \n\nUPDATE 10-17-19: Google Colab is now standard with 4 core CPUs, so this notebook will give different results than what is reported below, since Pytorch's indexing kernals get more efficient as the number of CPU cores increase. \n\nhttps:\u002F\u002Fcolab.research.google.com\u002Fdrive\u002F1PXhbmBZqtiq_NlfgUIaNpf_MfpiQSKKs\n\nThis notebook times the data transfer of 131,072 float32 embeddings of dimension 128, to and from the Cupy\u002FPytorch tensors and Pytorch variables, with n=100. Google Colab's CPU has 4 cores, which has an impact on the transfer speed. CPU's with a higher number of cores will see less of an advatage to using SpeedTorch. \n\nThe table below is a summary of the results. Transfering data from  Pytorch cuda tensors to the Cuda Pytorch embedding variable is faster than the SpeedTorch equivalent, but for all other transfer types, SpeedTorch is faster. And for the sum of both steps transferring to\u002Ffrom the Cuda Pytorch embedding, SpeedTorch is faster than the Pytorch equivalent for both the regular GPU and CPU Pinned tensors. \n\nI have noticed that different instances of Colab result in different speed results, so keep this in mind while reviewing these results. A personal run of the colab notebook may result in different values, though the order of magnetude of the results are generally the same. \n\nThe transfer times in the following tables are given in seconds. This benchmarking was preformed with a colab instance whose CPU has 2 cores. Colab has a Pro version of paid instances which are 4 core CPUs, so the following benchmarking would not reflect for those instances. \n\n| Tensor Type\t| To Cuda Pytorch Variable\t| Comparison |\n| --- | --- | --- |\n| SpeedTorch(cuda)\t| 0.0087\t| 6.2x Slower than Pytorch Equivalent |\n| SpeedTorch(PinnedCPU)\t| 0.0154\t| 3.1x Faster than Pytorch Equivalent |\n| Pytorch(cuda)\t| 0.0014\t| 6.2x Faster than SpeedTorch Equivalent |\n| Pytorch(PinnedCPU)\t| 0.0478\t| 3.1x Slower than SpeedTorch Equivalent |\n\t\t\n| Tensor Type\t| From Cuda Pytorch Variable\t| Comparison |\n| --- | --- | --- |\n| SpeedTorch(cuda)\t| 0.0035\t| 9.7x Faster than Pytorch Equivalent |\n| SpeedTorch(PinnedCPU)\t| 0.0065\t| 410x Faster than Pytorch Equivalent |\n| Pytorch(cuda)\t| 0.0341\t| 9.7x Slower than SpeedTorch Equivalent |\n| Pytorch(PinnedCPU)\t| 2.6641\t| 410x Slower than SpeedTorch Equivalent |\n\t\t\n| Tensor Type\t| Sum  of to\u002Ffrom Cuda Pytorch Variable\t| Comparison |\n| --- | --- | --- |\n| SpeedTorch(cuda)\t| 0.0122\t| 2.9x Faster than Pytorch Equivalent |\n| SpeedTorch(PinnedCPU)\t| 0.0219\t| 124x Faster than Pytorch Equivalent |\n| Pytorch(cuda)\t| 0.0355\t| 2.9x Slower than SpeedTorch Equivalent |\n| Pytorch(PinnedCPU)\t| 2.7119\t| 124x Slower than SpeedTorch Equivalent |\n\nSimilar benchmarks were calculated for transferring to\u002Ffrom Pytorch Cuda optimizers. The results are basically the same, here is the notebook used for the optimizers benchmarking\n\nhttps:\u002F\u002Fcolab.research.google.com\u002Fdrive\u002F1Y2nehd8Xj-ixfjkj2QWuA_UjQjBBHhJ5\n\n### Memory \n\nAlthough SpeedTorch's tensors are generally faster than Pytorch's, the drawback is SpeedTorch's tensors use more memory. However, because transferring data can happen more quickly, you can use SpeedTorch to augment the number of embeddings trained in your architecture by holding parameters in both the GPU And CPU. \n\nThis table is a summary of benchmarking done in Google Colab. From my experience, there seems to be some variation in the reported memory values in Colab, +-0.30 gb, so keep this in mind while reviewing these numbers. The values are for holding a 10,000,000x128 float32 tensor. \n\n|Tensor Type\t| CPU (gb)\t| GPU (gb)|\n| --- | --- | --- |\n|Cupy PinnedCPU |\t9.93 |\t0.06|\n|Pytorch PinnedCPU |\t6.59 |\t0.32|\n|Cupy Cuda |\t0.39 |\t9.61|\n|Pytorch Cuda |\t1.82 |\t5.09|\n\nAlthough Pytorch's time to\u002Ffrom for Pytorch GPU tensor \u003C-> Pytorch cuda Variable is not as fast as the Cupy equivalent, the speed is still workable. So if memory is still a concern, a best of both worlds approach would be to SpeedTorch's Cupy CPU Pinned Tensors to store parameters on the CPU, and SpeedTorch's Pytorch GPU tensors to store parameters on the GPU. \n\nThis is the notebook I used for measuring how much memory each variable type takes. \nhttps:\u002F\u002Fcolab.research.google.com\u002Fdrive\u002F1ZKY7PyuPAIDrnx2HdtbujWo8JuY0XkuE\nIf using this in Colab, you will need to restart the enviroment after each tensor creation, to get a measure for the next tensor. \n\n## What systems get a speed advantage?\n\nFor the CPU\u003C->GPU transfer, it depends on the amount of data being transfered, and the number of cores you have. Generally for 1-2 CPU cores SpeedTorch will be much faster. But as the number of CPU cores goes up, Pytorch's CPU\u003C->GPU indexing operations get more efficient. For more details on this, please see the next 'How it works' section. For an easy way to see if you get a speed advantage in your system, please run the benchmarking code on your system, but change the amount of data to reflect the amount that you will be working with in your application. \n\nFor the  GPU \u003C-> GPU transfer, if using ordinary indexing notations in vanilla Pytorch, all systems will get a speed increase because SpeedTorch bypasses a bug in Pytorch's indexing operations. But this bug can be avoided if using the nightly version, or just using different indexing notions, please see the 'How it works' section for more details. \n\n## How it works?\n\nUpdate 9-20-19: I initially had no idea why this is faster than using Pytorch tensors; I stumbled upon the speed advantage by accident. But one of the Pytorch developers on the Pytorch forum pointed it out. \n\nAs for the better CPU\u003C->GPU transfer, it's because SpeedTorch avoids a CPU indexing operation by masquarding CPU tensors as GPU tensors. The CPU index operation may be slow if working on with very few CPU cores, such as 2 in Google Colab, but may be faster if you have many cores.  It depends on how much data you're transfering and how many cores you have. \n\nAs for the better GPU\u003C->GPU transfer, it's because SpeedTorch avoids a bug in the indexing operation. This bug can also be avoided by using the nightly builds, or using `index_select` \u002F `index_copy_` instead of `a[idx]` notation in 1.1\u002F1.2. \n\nFor more details of this, please see this Pytorch post\n\nhttps:\u002F\u002Fdiscuss.pytorch.org\u002Ft\u002Fintroducing-speedtorch-4x-speed-cpu-gpu-transfer-110x-gpu-cpu-transfer\u002F56147\u002F2\n\nwhere a Pytorch engineer gives a detailed analysis on how the Cupy indexing kernals are resulting in speed ups in certain cases. It's not the transfer itself that is getting faster, but the indexing kernals which are being used. \n\nAs for how the memory management in Cupy works, I direct to these two stackoverflow questions I asked, where brilliant user Robert Crovella not only gave detailed explanations, but also figured out how to allocate pinned memory to Cupy arrays by developing his own memory allocator for Cupy. This is basically the core technology behind SpeedTorch. \n\nhttps:\u002F\u002Fstackoverflow.com\u002Fquestions\u002F57750125\u002Fcupy-outofmemoryerror-when-trying-to-cupy-load-larger-dimension-npy-files-in-me\n\nhttps:\u002F\u002Fstackoverflow.com\u002Fquestions\u002F57752516\u002Fhow-to-use-cuda-pinned-zero-copy-memory-for-a-memory-mapped-file\n\n## Guide\n\n### Geting Started\n\nSpeedTorch is pip installable. You need to have Cupy installed and imported before you import SpeedTorch. \n\n```\n!pip install SpeedTorch\nimport cupy\nimport SpeedTorch\n```\n\n### Using SpeedTorch to increase speed transfer of data from CPU to GPU\n\nThis colab notebook shows how to load data into SpeedTorch using its Data Gadget, and how to transfer this data to\u002Ffrom a Pytorch cuda variable. \n\nhttps:\u002F\u002Fcolab.research.google.com\u002Fdrive\u002F185Z5Gi62AZxh-EeMfrTtjqxEifHOBXxF\n\n\u003Cp align=\"center\">\n  \u003Cimg src=\"https:\u002F\u002Fi.imgur.com\u002FDc2DKsC.png\">\n\u003C\u002Fp>\n\nPlease see the speed benchmarking notebook to see the speed advantage of using SpeedTorch. \n\n### Using SpeedTorch to use non-sparse optimizers (in this case, Adamax) for sparse training\n\nFor people first trying to figure out how to use SpeedTorch, I recommend following this example, since word2vec is one of the more commonly known algorithms in machine learning. \n\nhttps:\u002F\u002Fcolab.research.google.com\u002Fdrive\u002F1ApJR3onbgQWM3FBcBKMvwaGXIDXlDXOt\n\nThe notebook shows how to train word2vec the regular way, then shows how to use SpeedTorch to train on the same data, using one of the optimizers normally not supported for sparse training. This is possible because since all the embeddings contained in the embedding variable has an update during each step, you can set `sparse=False` during initialization. \n\n### Augment training parameters via CPU storage\n\ntl;dr:\n\n**Normal training**: Pytorch embedding variables contain all embeddings. Pytorch optimizer contain all the corresponding parameter weights for each embedding. \n\n**SpeedTorch traing**: Pytorch embeddng variables only contain a batch of embeddings. Pytorch optimizer only contains all the corresponding parameter weights for that batch. SparseTorch tensors contain the rest, and exchanges the embeddings\u002Fweights with the Pytorch variable at each step. \n\nIn sparse training algorithms like word2vec, GloVe, or Neural Collaborative Filtering, only a fraction of the total parameters (embeddngs) are trained during every step. If your GPU can not handle all of your embeddings at a desired embedding size, an option would be to host some of your parameters on pinned CPU Cupy arrays, and transfer those parameters to your model tensors as needed. Doing this primary in Pytorch would be very slow, especially because transferring parameters between a Cuda mounted Pytorch variable and a pinned CPU pytorch tensor can take 2.5-3 seconds (on Google Colab). fortunately,\nthis step only takes 0.02-0.03 seconds with SpeedTorch!\n\n**Case Uses :**\n\n--2,829,853 book embeddings--\n\nSpeedTorch was used in training 2,829,853 books for a rare book recommender.\n\nhttps:\u002F\u002Fgithub.com\u002FSantosh-Gupta\u002FLit2Vec2\n\nhttps:\u002F\u002Fdevpost.com\u002Fsoftware\u002Flit2vec2\n\nEach book had an embedding of size of 400, but an embedding size of 496 could have been used, the 400 embedding size was due to limits of space on my Google Drive to store the trained embeddings :(. But the limits of the GPU RAM is no longer an issue :)\nHere is a direct link to a demo training notebook, which trains with a 496 embedding size using SpeedTorch\n\nNOTE: You need the version of the Colab notebook that has 25 gb of RAM, instead of the usual 12 gb. To get this type of instance, you need to crash your current instance due to overwhelming the RAM, and then a note in the bottom left corner asking if you would like to upgrade. You can do this by making a loop that keeps doubling the size of a numpy float matrix. \n\nhttps:\u002F\u002Fcolab.research.google.com\u002Fdrive\u002F1AqhT-HetihXMET1wJQROrC3Q9tFJqJ19\n\nHere is a directly link with the same model and data, but doesn't use SpeedTorch\n\nhttps:\u002F\u002Fcolab.research.google.com\u002Fdrive\u002F1idV1jBOUZVPCfdsy40wIrRPHeDOanti_\n\nUsing the orthodox training method, the largest embedding size that colab is able to handle is 255-260, any higher than that and a cuda error will occur\n\n`RuntimeError: CUDA out of memory. Tried to allocate 2.74 GiB (GPU 0; 11.17 GiB total capacity; 8.22 GiB already allocated; 2.62 GiB free; 5.05 MiB cached)`\n\n--14,886,544 research paper embeddings--\n\nhttps:\u002F\u002Fgithub.com\u002FSantosh-Gupta\u002FResearch2Vec2\n\nSpeedTorch can allow me to train 14,886,544 research paper embeddings at an embedding size of 188, by allowing my to store my target embeddings on the CPU, while keeping my context embeddings on the GPU (SGD optimizer was used, so there are no optimizer weights). \n\nHere is a direct link to the notebook. \n\nhttps:\u002F\u002Fcolab.research.google.com\u002Fdrive\u002F1saKzsaHoy6O_U1DF_z15_Qkr5YLNI_GR\n\nNOTE: You need the version of the Colab notebook that has 25 gb of RAM, instead of the usual 12 gb. To get this type of instance, you need to crash your current instance due to overwhelming the RAM, and then a note in the bottom left corner asking if you would like to upgrade. You can do this by making a loop that keeps doubling the size of a numpy float matrix. \n\nWithout SpeedTorch, only an embedding size of 94-96 can be used on Google Colab Tesla K80 GPU before an `RuntimeError: CUDA out of memory` error. Here is a version of the training without using SpeedTorch. \n\nhttps:\u002F\u002Fcolab.research.google.com\u002Fdrive\u002F1jh7RUgeajhdWdGNfWG3Twm1ZjyTQU0KR\n\n### Best Practices\n\n1) Whenever using the Cupy GPU tensors, initialize these before any pinned CPU tensors. This is because the initialization of the Cupy GPU tensors seem to uses a solid amount of CPU RAM. So if you're limited on CPU RAM, and you already have your pinned CPU tensors in memory, then initializing the cupy GPU tensors may cause a crash. \n\n2) If you're able to fit all of your parameters in your GPU memory, use pure Pytorch since this is the fastest option for training. But if you can't fit all your parameters in memory, split your parameters (keep in mind that your optimizers also have weights) between SpeedTorch's Cupy cuda tensors and SpeedTorch's Cupy pinned CPU tensors; this is the 2nd fastest options. But, if you're still not able to fit all your parameters into memory that way, then split your parameters between SpeedTorch's Cupy pinned CPU tensors, and SpeedTorch's Pytorch cuda tensors; this is slower than both options, but uses less GPU memory. For the 3rd option, here are two notebooks which shows an example of this https:\u002F\u002Fcolab.research.google.com\u002Fdrive\u002F1AqhT-HetihXMET1wJQROrC3Q9tFJqJ19 , https:\u002F\u002Fcolab.research.google.com\u002Fdrive\u002F1saKzsaHoy6O_U1DF_z15_Qkr5YLNI_GR\n\n3) After training, saving any cuda variables will cause an increase in memory usage, and may cause a crash, especially with Cupy. If you're at the limits of your RAM. In this case, use the `getNumpyVersion` method to get a numpy version of your tensor, and then use use numpy.save or hdpy\u002Fpytables to save your numpy array. Numpy save is more lightweight. \n\n## Need Help?\n\nEither open an issue, or chat with me directory on Gitter here https:\u002F\u002Fgitter.im\u002FSpeedTorch\n\n## Future Work\n\nI am looking incoporate more functionalities around the fast CPU -> GPU transfer. If you have an idea, please post a Github Issue. \n\n## Experimental\n\nIn addition the the Cupy GPU\u002Fpinned CPU and Pytorch GPU tensors, SpeedTorch also has Pytorch pinned CPU tensors, and Cupy memmap GPU\u002Fpinned CPU tensors. I have not found a solid use for these sorts of tensors, but they're fully coded and availible for use. \n\nhttps:\u002F\u002Fgithub.com\u002FSantosh-Gupta\u002FSpeedTorch\u002Ftree\u002Fmaster\u002FSpeedTorch\n\nOne area I would like to look at is if there is a way to have RAM memory reduction by using Cupy Memmaps. So far they use just as much memory as the live versions. \n\n## Documentation \n\n### Class ModelFactory\n\n```python\nModelFactory(model_variable,  total_classes,  embed_dimension, datatype = 'float32', CPUPinn = False)\n```\n\nCreates switchers for model variables using Cupy. Switches variables from your full embedding collection and your model batch collection. Each variable needs its own switcher. \n\nExample:\n\n```python\nuEmbed_switcher = SpeedTorch.ModelFactory( skip_gram_modelSparse.u_embeddings, total_classes=50000, embed_dimension=128)\n```\n\nArguments:\n\n`model_variable`: Specific variable from your model you would like to create a switcher for.\n\n`total_classes`: The total amount of embeddings to be trained. \n\n`embed_dimension`: Dimension of the embeddings.\n\n`datatype` (optional): Datatype for the variable. Default is 'float32'. \n\n`CPUPinn` (optional): Pin your full embedding collection to CPU. Spares GPU memory, but data transfer will be slower. Default is False. \n\nMethods:\n\n`zerosInit()` : Initializes the variable switcher full collection with zeros:\n\n`uniformDistributionInit(low, high)`: Initializes the variable switcher full collection with a uniform distribution from `low` to `high`\n\n`normalDistributionInit(mean, stdDev)`: Initializes the variable switcher full collection with a normal distribution with a mean of `mean` and a standard deviation of `stdDev`\n\n`variableTransformer( batchSize, posPerBatch,  negPerBatch = None )`: Sets up a dummy input to be used for the forward step of you model. `batchSize` is the size of your batch, and `posPerBatch` is the number of positive examples per batch. If a second dummy input is needed for the negative examples, `negPerBatch` (optional) can be set to the number of negative examples, and two dummy inputs will be returned instead of one. \n\n`beforeForwardPass(retrievedPosIndexes , retrievedNegIndexes = None)`: Switches embeddings from the full embeddings collection to your model embeddings. `retrievedPosIndexes` is the indexes of the positive samples to be retrieved. If negative samples are to be retrieved as well, a value for `retrievedNegIndexes` (optional) can be passed as well. \n\n`afterOptimizerStep( retrievedPosIndexes , retrievedNegIndexes = None)`: Switches updated embeddings from your model to the full embeddings collection. `retrievedPosIndexes` is the indexes of the positive samples that were retrieved. If negative samples were retrieved as well, a value for `retrievedNegIndexes` (optional) can be passed as well. \n\n`saveCupy(saveFileName)`: Save tensor to .npy file. \n\n`loadCupy(loadFileName)`: Load tensor from .npy file. \n\n`getNumpyVersion`: Get numpy version of tensor. \n\n### Class OptimizerFactory\n\n```pyton\nOptimizerFactory( given_optimizer,  total_classes,  embed_dimension, model, variable_name, dtype='float32' , CPUPinn = False)\n```\n\nCreates switchers for optimizer variables using Cupy. Switches variables from your full embedding collection and your optimizer batch collection. Each variable needs its own switcher. \n\nExample:\n\n```python\nuAdagrad_switcher = SpeedTorch.OptimizerFactory(given_optimizer,  total_classes,  embed_dimension, model, variable_name, dtype='float32', CPUPinn = False)\n```\n\nArguments:\n\n`given_optimizer`: The optimizer initialized with your model weights. If using for embeddings training, remember to set the `sparse` parameter to `False`. Currently, supported optimizers are SparseAdam, Adadelta, Adamax, Adam, AdamW, ASGD, and RMSprop. Rprop is also inlcuded, but needs the first forward pass, and `loss.backward()` step to be completed for initializing the OptimizerFactory instance. This is due to the Rprop optimizer needing gradients of its parameters for initialization.  \n\n`total_classes`: The total amount of embeddings to be trained. \n\n`embed_dimension`: Dimension of the embeddings.\n\n`model`: The instance of your model. \n\n`variable_name`: Exact name of the variable defined in your model. \n\n`dtype` (optional): Data type of your variable. Default is 'float32'\n\n`CPUPinn` (optional): Pin your full optimizer variable weight collection to CPU. Spares GPU memory, but data transfer will be slower. Default is False. \n\nMethods:\n\n`optInit`: Initializes the optimizer variable switcher. \n\n`beforeForwardPass(retrievedPosIndexes , retrievedNegIndexes = None)`: Switches optimizer variable weights from the full weights collection to optimizer weight tensor. `retrievedPosIndexes` is the indexes of the positive samples to be retrieved. If negative samples are to be retrieved as well, a value for `retrievedNegIndexes` (optional) can be passed as well. \n\n`afterOptimizerStep( retrievedPosIndexes , retrievedNegIndexes = None)`: Switches optimizer variable weights from your optimizer to the full weights collection. `retrievedPosIndexes` is the indexes of the positive samples that were retrieved. If negative samples were retrieved as well, a value for `retrievedNegIndexes` (optional) can be passed as well. \n\n### Class DataGadget\n\nCreates a tensor whose main function is to transfer it's contents to a Pytorch cuda variable. \n\n```pyton\nDataGadget( fileName, CPUPinn=False)\n```\n\nArguments:\n\n`fileName`: Location of data .npy file to be opened\n\n`CPUPinn`:  (optional): Pin your data to CPU. Default is False. \n\nMethods:\n\n`getData(indexes)`: Retrieves data in a format that is ready to be accepted by a Pytorch Cuda Variable. `indexes` is the indexes of the tensor from which to retrieve data from. \n\n`insertData(dataObject, indexes)`: Insert data from a Pytorch Cuda Variable. `dataObject` is the Pytorch cuda variable tensor data from which the data is is going to be retrived from, and `indexes` of the tensor from which to retrieve data from. \n\n`saveCupy(saveFileName)`: Save tensor to .npy file. \n\n`loadCupy(loadFileName)`: Load new tensor from .npy file. \n\n`getNumpyVersion`: Get numpy version of tensor. \n\nPlease see this notebook on how to use the data gadget\n\nhttps:\u002F\u002Fcolab.research.google.com\u002Fdrive\u002F185Z5Gi62AZxh-EeMfrTtjqxEifHOBXxF\n\n### Class PytorchModelFactory\n\n```python\nPytorchModelFactory(model_variable,  total_classes,  embed_dimension, datatype = 'float32', deviceType = 'cuda', pinType = False)\n```\n\nCreates switchers for model variables using Pytorch tensors. Switches variables from your full embedding collection and your model batch collection. Each variable needs its own switcher. \n\nExample:\n\n```python\nuEmbed_switcher = SpeedTorch.PytorchModelFactory( skip_gram_modelSparse.u_embeddings, total_classes=50000, embed_dimension=128)\n```\n\nArguments:\n\n`model_variable`: Specific variable from your model you would like to create a switcher for.\n\n`total_classes`: The total amount of embeddings to be trained. \n\n`embed_dimension`: Dimension of the embeddings.\n\n`datatype` (optional): Datatype for the variable. Default is 'float32'. \n\n`deviceType` (optional): Set device either to 'cuda' or 'cpu'. Default is 'cuda'\n\n`pinType` (optional): If device is set to 'cpu', you can specify using pinned memory. Default is 'False'. \n\n\nMethods:\n\n`zerosInit()` : Initializes the variable switcher full collection with zeros:\n\n`uniformDistributionInit(low, high)`: Initializes the variable switcher full collection with a uniform distribution from `low` to `high`\n\n`normalDistributionInit(mean, stdDev)`: Initializes the variable switcher full collection with a normal distribution with a mean of `mean` and a standard deviation of `stdDev`\n\n`customInit(initFunction, *args)`: Use any Pytorch initializer for the variable switchers full collection. Pass the initializer using `initFunction` and its corresponding arguments using `*args`.\n\n`variableTransformer(batchSize, posPerBatch,  negPerBatch = None )`: Sets up a dummy input to be used for the forward step of you model. `batchSize` is the size of your batch, and `posPerBatch` is the number of positive examples per batch. If a second dummy input is needed for the negative examples, `negPerBatch` (optional) can be set to the number of negative examples, and two dummy inputs will be returned instead of one. \n\n`beforeForwardPass(retrievedPosIndexes , retrievedNegIndexes = None)`: Switches embeddings from the full embeddings collection to your model embeddings. `retrievedPosIndexes` is the indexes of the positive samples to be retrieved. If negative samples are to be retrieved as well, a value for `retrievedNegIndexes` (optional) can be passed as well. \n\n`afterOptimizerStep(retrievedPosIndexes , retrievedNegIndexes = None)`: Switches updated embeddings from your model to the full embeddings collection. `retrievedPosIndexes` is the indexes of the positive samples that were retrieved. If negative samples were retrieved as well, a value for `retrievedNegIndexes` (optional) can be passed as well. \n\n`saveTorch(saveFileName)`: Save tensor to file using torch.save\n\n`loadTorch(loadFileName)`: Load tensor using torch.load\n\n`getNumpyVersion`: Get numpy version of tensor. \n\n### Class PytorchOptimizerFactory\n\n```pyton\nPytorchOptimizerFactory( given_optimizer,  total_classes,  embed_dimension, model, variable_name, dtype='float32', deviceType = 'cuda', pinType = False)\n```\n\nCreates switchers for optimizer variables using Pytorch tensors. Switches variables from your full embedding collection and your optimizer batch collection. Each variable needs its own switcher. \n\nExample:\n\n```python\nuAdagrad_switcher = SpeedTorch.PytorchOptimizerFactory(given_optimizer,  total_classes,  embed_dimension, model, variable_name, dtype='float32')\n```\n\nArguments:\n\n`given_optimizer`: The optimizer initialized with your model weights. If using for embeddings training, remember to set the `sparse` parameter to `False`. Currently, supported optimizers are SparseAdam, Adadelta, Adamax, Adam, AdamW, ASGD, and RMSprop. Rprop is also inlcuded, but needs the first forward pass, and `loss.backward()` step to be completed for initializing the OptimizerFactory instance. This is due to the Rprop optimizer needing gradients of its parameters for initialization.  \n\n`total_classes`: The total amount of embeddings to be trained. \n\n`embed_dimension`: Dimension of the embeddings.\n\n`model`: The instance of your model. \n\n`variable_name`: Exact name of the variable defined in your model. \n\n`dtype` (optional): Data type of your variable. Default is 'float32'\n\n`deviceType` (optional): Set device either to 'cuda' or 'cpu'. Default is 'cuda'\n\n`pinType` (optional): If device is set to 'cpu', you can specify using pinned memory. Default is 'False'. \n\n\nMethods:\n\n`optInit`: Initializes the optimizer variable switcher. \n\n`beforeForwardPass(retrievedPosIndexes , retrievedNegIndexes = None)`: Switches optimizer variable weights from the full weights collection to optimizer weight tensor. `retrievedPosIndexes` is the indexes of the positive samples to be retrieved. If negative samples are to be retrieved as well, a value for `retrievedNegIndexes` (optional) can be passed as well. \n\n`afterOptimizerStep( retrievedPosIndexes , retrievedNegIndexes = None)`: Switches optimizer variable weights from your optimizer to the full weights collection. `retrievedPosIndexes` is the indexes of the positive samples that were retrieved. If negative samples were retrieved as well, a value for `retrievedNegIndexes` (optional) can be passed as well. \n\n## Citing SpeedTorch:\nIf you use SpeedTorch in your research or wish to cite, please cite with:\n\n@misc{\n\n  title={SpeedTorch},\n  \n  author={Santosh Gupta},\n  \n  howpublished={\\url{github.com\u002FSantosh-Gupta\u002FSpeedTorch}},\n  \n  year={2019}\n  \n}\n","\u003Cp align=\"center\">\n  \u003Cimg src=\"https:\u002F\u002Fi.imgur.com\u002Fwr4VaUV.png?1\">\n\u003C\u002Fp>\n\n# SpeedTorch\n\n[![加入 https:\u002F\u002Fgitter.im\u002FSpeedTorch\u002Fcommunity 的聊天](https:\u002F\u002Fbadges.gitter.im\u002FSpeedTorch\u002Fcommunity.svg)](https:\u002F\u002Fgitter.im\u002FSpeedTorch\u002Fcommunity?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![下载量](https:\u002F\u002Foss.gittoolsai.com\u002Fimages\u002FSantosh-Gupta_SpeedTorch_readme_ec93fc81d569.png)](https:\u002F\u002Fpepy.tech\u002Fproject\u002Fspeedtorch) [![每周下载量](https:\u002F\u002Foss.gittoolsai.com\u002Fimages\u002FSantosh-Gupta_SpeedTorch_readme_ec93fc81d569.png\u002Fweek)](https:\u002F\u002Fpepy.tech\u002Fproject\u002Fspeedtorch\u002Fweek)\n\n在特定情况下，实现更快的固定 CPU 张量与 GPU PyTorch 变量之间的传输，以及 GPU 张量与 GPU PyTorch 变量之间的传输。\n\n## 更新 9-29-19\n\n由于在某些系统上，使用固定的 PyTorch CPU 张量比使用 Cupy 张量更快（详情请参阅“工作原理”部分），我创建了通用的 PyTorch 张量类 `PytorchModelFactory` 和 `PytorchOptimizerFactory`，它们可以指定将张量设置为 `cuda` 或 `cpu`，并且如果使用 `cpu`，还可以选择是否将其内存固定。原有的 `GPUPytorchModelFactory` 和 `GPUPytorchOptimizerFactory` 类仍然保留在库中，因此现有使用 SpeedTorch 的代码不会受到影响。文档也已更新，加入了这些新类。\n\n## 它是什么？\n\n该库的核心是固定在 CPU 上的 Cupy 张量，相比普通的 PyTorch 固定 CPU 张量，它可以使 CPU 到 GPU 的传输速度提升 **3.1 倍**，而 GPU 到 CPU 的传输速度则可提升至 **410 倍**。具体速度取决于数据量和系统中的 CPU 核心数（更多细节请参阅“工作原理”部分）。\n\n该库还包含用于嵌入训练的函数；当嵌入处于空闲状态时，可以将其存储在 CPU 内存中，从而节省 GPU 内存。\n\n## 灵感来源\n\n我最初创建这个库是为了帮助训练大量嵌入，而 GPU 可能难以容纳这些数据。为此，我发现将部分嵌入存储在 CPU 上可以帮助实现这一目标。嵌入系统采用稀疏训练方式——只有总参数的一小部分参与前向传播或更新步骤，其余部分则处于空闲状态。因此，我想：为什么不在训练过程中将空闲参数从 GPU 上移开呢？这就需要快速的 CPU 到 GPU 数据传输。\n\n如需了解完整背景，请访问 Devpost 页面：\n\nhttps:\u002F\u002Fdevpost.com\u002Fsoftware\u002Fspeedtorch-6w5unb\n\n## 快速的 CPU 到 GPU 传输能为我带来什么？（远超你的想象）\n\n借助快速的 CPU 到 GPU 传输，我们可以开发出许多有趣的方法来实现以前被认为不可能的功能。\n\n🏎️    将 SpeedTorch 集成到你的数据管道中，实现 CPU 与 GPU 之间快速的数据传输。\n\n🏎️    通过 CPU 存储扩充训练参数。只要你的 CPU 内存足够，就可以存储任意数量的嵌入，而无需担心 GPU 内存不足的问题。\n\n🏎️    使用 Adadelta、Adamax、RMSprop、Rprop、ASGD、AdamW 和 Adam 优化器进行稀疏嵌入训练。过去，只有 SparseAdam、Adagrad 和 SGD 适合处理稀疏梯度，因为只有这些优化器直接支持稀疏梯度。\n\n\u003Cp align=\"center\">\n  \u003Cimg src=\"https:\u002F\u002Fi.imgur.com\u002F6o8C1BP.gif\">\n\u003C\u002Fp>\n\n## 基准测试\n\n### 速度\n\n（编辑于 9-20-19，一位 PyTorch 开发者指出了原始基准测试代码中的一些小错误，数值和代码均已更新）\n\n这里有一个笔记本，比较了通过 SpeedTorch 和 PyTorch 张量进行传输的效果，包括固定 CPU 和 CUDA 张量两种情况。所有测试均在配备 Tesla K80 GPU 和 2 核 CPU 的 Colab 实例上完成。\n\n更新 10-17-19：Google Colab 现在默认配备 4 核 CPU，因此该笔记本的结果会与下方报告的不同，因为随着 CPU 核心数的增加，PyTorch 的索引内核效率也会提高。CPU 核心数更多的系统在使用 SpeedTorch 时优势会相对减小。\n\nhttps:\u002F\u002Fcolab.research.google.com\u002Fdrive\u002F1PXhbmBZqtiq_NlfgUIaNpf_MfpiQSKKs\n\n此笔记本测量了 131,072 个维度为 128 的 float32 嵌入，在 Cupy\u002FPyTorch 张量和 PyTorch 变量之间来回传输的时间，重复次数为 n=100。Google Colab 的 CPU 是 4 核的，这会影响传输速度。CPU 核心数较多的系统使用 SpeedTorch 的优势会较小。\n\n下表总结了测试结果。从 PyTorch CUDA 张量传输数据到 CUDA PyTorch 嵌入变量的速度比 SpeedTorch 对应操作更快，但在其他所有传输类型中，SpeedTorch 都更快。而对于往返 CUDA PyTorch 嵌入变量的总时间，无论是普通 GPU 张量还是固定 CPU 张量，SpeedTorch 都比 PyTorch 对应操作更快。\n\n我注意到不同 Colab 实例的运行结果可能会有所不同，因此在查看这些结果时请注意这一点。亲自运行该 Colab 笔记本可能会得到不同的数值，不过结果的数量级通常是一致的。\n\n以下表格中的传输时间单位为秒。本次基准测试是在 CPU 为 2 核的 Colab 实例上进行的。Colab 还有付费的 Pro 版本，配备 4 核 CPU，因此以下基准测试结果并不适用于那些实例。\n\n| 张量类型\t| 传输至 CUDA PyTorch 变量\t| 对比 |\n| --- | --- | --- |\n| SpeedTorch(cuda)\t| 0.0087\t| 比 PyTorch 对应操作慢 6.2 倍 |\n| SpeedTorch(PinnedCPU)\t| 0.0154\t| 比 PyTorch 对应操作快 3.1 倍 |\n| PyTorch(cuda)\t| 0.0014\t| 比 SpeedTorch 对应操作快 6.2 倍 |\n| PyTorch(PinnedCPU)\t| 0.0478\t| 比 SpeedTorch 对应操作慢 3.1 倍 |\n\n| 张量类型\t| 从 CUDA PyTorch 变量传输\t| 对比 |\n| --- | --- | --- |\n| SpeedTorch(cuda)\t| 0.0035\t| 比 PyTorch 对应操作快 9.7 倍 |\n| SpeedTorch(PinnedCPU)\t| 0.0065\t| 比 PyTorch 对应操作快 410 倍 |\n| PyTorch(cuda)\t| 0.0341\t| 比 SpeedTorch 对应操作慢 9.7 倍 |\n| PyTorch(PinnedCPU)\t| 2.6641\t| 比 SpeedTorch 对应操作慢 410 倍 |\n\n| 张量类型\t| 往返 CUDA PyTorch 变量的总时间\t| 对比 |\n| --- | --- | --- |\n| SpeedTorch(cuda)\t| 0.0122\t| 比 PyTorch 对应操作快 2.9 倍 |\n| SpeedTorch(PinnedCPU)\t| 0.0219\t| 比 PyTorch 对应操作快 124 倍 |\n| PyTorch(cuda)\t| 0.0355\t| 比 SpeedTorch 对应操作慢 2.9 倍 |\n| PyTorch(PinnedCPU)\t| 2.7119\t| 比 SpeedTorch 对应操作慢 124 倍 |\n\n类似的基准测试也针对 PyTorch CUDA 优化器的传输进行了计算。结果基本相同，以下是用于优化器基准测试的笔记本：\n\nhttps:\u002F\u002Fcolab.research.google.com\u002Fdrive\u002F1Y2nehd8Xj-ixfjkj2QWuA_UjQjBBHhJ5\n\n### 内存\n\n尽管 SpeedTorch 的张量通常比 PyTorch 的更快，但缺点是 SpeedTorch 的张量会占用更多内存。不过，由于数据传输速度更快，你可以利用 SpeedTorch 在 GPU 和 CPU 上同时保存参数，从而增加架构中训练的嵌入数量。\n\n下表是在 Google Colab 中进行基准测试的汇总。根据我的经验，Colab 报告的内存值似乎存在一些波动，大约在 ±0.30 GB 左右，因此在查看这些数值时请注意这一点。这些数值是针对一个 10,000,000×128 的 float32 张量而言的。\n\n| 张量类型       | CPU (GB)   | GPU (GB)   |\n| ---            | ---        | ---        |\n| Cupy PinnedCPU | 9.93       | 0.06       |\n| Pytorch PinnedCPU | 6.59     | 0.32       |\n| Cupy Cuda      | 0.39       | 9.61       |\n| Pytorch Cuda   | 1.82       | 5.09       |\n\n虽然 PyTorch GPU 张量与 PyTorch CUDA 变量之间的传输时间不如 Cupy 的对应操作快，但速度仍然可以接受。因此，如果内存仍然是一个问题，一种折中的方法是使用 SpeedTorch 的 Cupy CPU 固定张量来在 CPU 上存储参数，而使用 SpeedTorch 的 PyTorch GPU 张量来在 GPU 上存储参数。\n\n这是我用来测量每种变量类型占用多少内存的笔记本：\nhttps:\u002F\u002Fcolab.research.google.com\u002Fdrive\u002F1ZKY7PyuPAIDrnx2HdtbujWo8JuY0XkuE\n如果在 Colab 中使用此笔记本，每次创建完一个张量后都需要重启环境，以便为下一个张量获取准确的测量结果。\n\n## 哪些系统能获得速度优势？\n\n对于 CPU↔GPU 数据传输，这取决于传输的数据量以及你拥有的核心数。一般来说，对于 1–2 个 CPU 核心，SpeedTorch 会快得多。但随着 CPU 核心数的增加，PyTorch 的 CPU↔GPU 索引操作效率会更高。有关这方面的详细信息，请参阅下一节“工作原理”。如果你想简单地判断自己的系统是否能从中受益，可以在本地运行基准测试代码，并将数据量调整为你实际应用中会处理的数量。\n\n对于 GPU↔GPU 数据传输，如果使用原生 PyTorch 的常规索引方式，所有系统都会获得速度提升，因为 SpeedTorch 绕过了 PyTorch 索引操作中的一个 bug。不过，这个 bug 可以通过使用 nightly 版本或改用不同的索引方式来避免，详情请参阅“工作原理”部分。\n\n## 如何工作？\n\n更新：2019 年 9 月 20 日——起初我并不清楚为什么 SpeedTorch 比 PyTorch 张量更快；我只是偶然发现了这一速度优势。后来，PyTorch 论坛上的一位开发者指出了其中的原因。\n\n至于更好的 CPU↔GPU 传输，这是因为 SpeedTorch 通过将 CPU 张量伪装成 GPU 张量来避免一次 CPU 索引操作。如果 CPU 核心较少（例如 Google Colab 中只有 2 个核心），CPU 索引操作可能会很慢；但如果核心较多，则可能更快。具体效果取决于你要传输的数据量以及你的核心数量。\n\n至于更好的 GPU↔GPU 传输，这是因为 SpeedTorch 避免了索引操作中的一个 bug。这个 bug 也可以通过使用 nightly 构建版本，或者在 PyTorch 1.1\u002F1.2 中使用 `index_select` 或 `index_copy_` 而不是 `a[idx]` 语法来避免。\n\n有关详细信息，请参阅以下 PyTorch 帖子：\n\nhttps:\u002F\u002Fdiscuss.pytorch.org\u002Ft\u002Fintroducing-speedtorch-4x-speed-cpu-gpu-transfer-110x-gpu-cpu-transfer\u002F56147\u002F2\n\n其中一位 PyTorch 工程师详细分析了 Cupy 索引内核在某些情况下如何带来速度提升。实际上，加快速度的并不是传输本身，而是所使用的索引内核。\n\n关于 Cupy 的内存管理机制，我建议参考我在 Stack Overflow 上提出的两个问题。聪明的用户 Robert Crovella 不仅给出了详细的解释，还通过开发自己的 Cupy 内存分配器，找到了为 Cupy 数组分配固定内存的方法。这基本上就是 SpeedTorch 背后的核心技术。\n\nhttps:\u002F\u002Fstackoverflow.com\u002Fquestions\u002F57750125\u002Fcupy-outofmemoryerror-when-trying-to-cupy-load-larger-dimension-npy-files-in-me\nhttps:\u002F\u002Fstackoverflow.com\u002Fquestions\u002F57752516\u002Fhow-to-use-cuda-pinned-zero-copy-memory-for-a-memory-mapped-file\n\n## 使用指南\n\n### 开始使用\n\nSpeedTorch 可以通过 pip 安装。在导入 SpeedTorch 之前，你需要先安装并导入 Cupy。\n\n```\n!pip install SpeedTorch\nimport cupy\nimport SpeedTorch\n```\n\n### 使用 SpeedTorch 提高 CPU 到 GPU 的数据传输速度\n\n这个 Colab 笔记本展示了如何使用 SpeedTorch 的 Data Gadget 将数据加载到 SpeedTorch 中，以及如何将这些数据与 PyTorch 的 CUDA 变量进行双向传输。\n\nhttps:\u002F\u002Fcolab.research.google.com\u002Fdrive\u002F185Z5Gi62AZxh-EeMfrTtjqxEifHOBXxF\n\n\u003Cp align=\"center\">\n  \u003Cimg src=\"https:\u002F\u002Fi.imgur.com\u002FDc2DKsC.png\">\n\u003C\u002Fp>\n\n请参阅速度基准测试笔记本，以了解使用 SpeedTorch 所带来的速度优势。\n\n### 使用 SpeedTorch 对稀疏数据使用非稀疏优化器（如 Adamax）\n\n对于初次尝试使用 SpeedTorch 的人，我建议按照这个示例操作，因为 Word2Vec 是机器学习中较为常见的算法之一。\n\nhttps:\u002F\u002Fcolab.research.google.com\u002Fdrive\u002F1ApJR3onbgQWM3FBcBKMvwaGXIDXlDXOt\n\n该笔记本首先展示了如何以常规方式训练 Word2Vec，然后演示了如何使用 SpeedTorch 在相同数据上进行训练，采用一种通常不支持稀疏训练的优化器。之所以可行，是因为嵌入变量中的所有嵌入在每一步都会被更新，因此在初始化时可以将 `sparse` 参数设置为 `False`。\n\n### 通过 CPU 存储扩充训练参数\n\n简而言之：\n\n**常规训练**：PyTorch 的嵌入变量包含所有嵌入；PyTorch 优化器则包含每个嵌入对应的所有参数权重。\n\n**SpeedTorch 训练**：PyTorch 的嵌入变量仅包含一批嵌入；PyTorch 优化器也只包含该批次对应的参数权重。其余部分由 SparseTorch 张量存储，并在每一步与 PyTorch 变量交换嵌入或权重。\n\n在诸如 word2vec、GloVe 或神经协同过滤等稀疏训练算法中，每一步仅训练总参数（嵌入）的一小部分。如果您的 GPU 无法以期望的嵌入维度容纳所有嵌入，一种选择是将部分参数托管在固定在内存中的 CPU Cupy 数组上，并在需要时将其传输到模型张量中。如果主要在 PyTorch 中执行此操作会非常缓慢，尤其是当在挂载了 CUDA 的 PyTorch 变量和固定在内存中的 CPU PyTorch 张量之间传输参数时，可能需要 2.5 到 3 秒（在 Google Colab 上）。幸运的是，使用 SpeedTorch 这一步仅需 0.02 到 0.03 秒！\n\n**应用场景：**\n\n--2,829,853 本书的嵌入--\n\nSpeedTorch 被用于为一本稀有书籍推荐系统训练 2,829,853 本书的嵌入。\n\nhttps:\u002F\u002Fgithub.com\u002FSantosh-Gupta\u002FLit2Vec2\n\nhttps:\u002F\u002Fdevpost.com\u002Fsoftware\u002Flit2vec2\n\n每本书的嵌入维度为 400，但理论上可以使用 496 维的嵌入。之所以采用 400 维，是因为我存储训练后嵌入的 Google Drive 空间有限 :( 。不过，现在 GPU 内存的限制不再是问题了 :) 以下是一个演示训练笔记本的直接链接，它使用 SpeedTorch 以 496 维嵌入进行训练。\n\n注意：您需要使用具有 25 GB RAM 的 Colab 笔记本版本，而不是通常的 12 GB。要获得这种类型的实例，您需要先让当前实例因内存不足而崩溃，随后左下角会出现提示，询问您是否希望升级。您可以通过编写一个不断将 NumPy 浮点矩阵大小翻倍的循环来实现这一点。\n\nhttps:\u002F\u002Fcolab.research.google.com\u002Fdrive\u002F1AqhT-HetihXMET1wJQROrC3Q9tFJqJ19\n\n以下是使用相同模型和数据，但未使用 SpeedTorch 的直接链接：\n\nhttps:\u002F\u002Fcolab.research.google.com\u002Fdrive\u002F1idV1jBOUZVPCfdsy40wIrRPHeDOanti_\n\n采用传统训练方法时，Colab 能够处理的最大嵌入维度为 255–260，超过这个值就会出现 CUDA 内存不足错误：\n\n`RuntimeError: CUDA out of memory. Tried to allocate 2.74 GiB (GPU 0; 11.17 GiB total capacity; 8.22 GiB already allocated; 2.62 GiB free; 5.05 MiB cached)`\n\n--14,886,544 篇研究论文的嵌入--\n\nhttps:\u002F\u002Fgithub.com\u002FSantosh-Gupta\u002FResearch2Vec2\n\n借助 SpeedTorch，我可以在 GPU 上保留上下文嵌入的同时，将目标嵌入存储在 CPU 上，从而以 188 维的嵌入维度训练 14,886,544 篇研究论文的嵌入（由于使用了 SGD 优化器，因此没有优化器权重）。\n\n以下是该笔记本的直接链接：\n\nhttps:\u002F\u002Fcolab.research.google.com\u002Fdrive\u002F1saKzsaHoy6O_U1DF_z15_Qkr5YLNI_GR\n\n注意：您需要使用具有 25 GB RAM 的 Colab 笔记本版本，而不是通常的 12 GB。要获得这种类型的实例，您需要先让当前实例因内存不足而崩溃，随后左下角会出现提示，询问您是否希望升级。您可以通过编写一个不断将 NumPy 浮点矩阵大小翻倍的循环来实现这一点。\n\n如果没有 SpeedTorch，在 Google Colab 的 Tesla K80 GPU 上，嵌入维度只能达到 94–96，否则会出现 `RuntimeError: CUDA out of memory` 错误。以下是未使用 SpeedTorch 的训练版本：\n\nhttps:\u002F\u002Fcolab.research.google.com\u002Fdrive\u002F1jh7RUgeajhdWdGNfWG3Twm1ZjyTQU0KR\n\n### 最佳实践\n\n1) 使用 Cupy GPU 张量时，请务必先初始化它们，再初始化固定在内存中的 CPU 张量。这是因为初始化 Cupy GPU 张量似乎会占用大量 CPU 内存。因此，如果您 CPU 内存有限，且已将固定在内存中的 CPU 张量加载到内存中，则初始化 Cupy GPU 张量可能会导致崩溃。\n\n2) 如果您的所有参数都能装入 GPU 内存，请使用纯 PyTorch，因为这是最快的训练方式。但如果无法将所有参数装入内存，则应将参数（请注意，优化器也有权重）在 SpeedTorch 的 Cupy CUDA 张量和 Cupy 固定在内存中的 CPU 张量之间分配；这是第二快的方式。然而，即便如此仍无法将所有参数装入内存，则可将参数在 SpeedTorch 的 Cupy 固定在内存中的 CPU 张量和 SpeedTorch 的 PyTorch CUDA 张量之间分配；这种方式虽然比前两种慢，但使用的 GPU 内存更少。关于第三种方式，这里有两个示例笔记本：https:\u002F\u002Fcolab.research.google.com\u002Fdrive\u002F1AqhT-HetihXMET1wJQROrC3Q9tFJqJ19 和 https:\u002F\u002Fcolab.research.google.com\u002Fdrive\u002F1saKzsaHoy6O_U1DF_z15_Qkr5YLNI_GR。\n\n3) 训练完成后，保存任何 CUDA 变量都会增加内存使用量，甚至可能导致崩溃，尤其是在使用 Cupy 时。如果您已经接近内存上限，建议使用 `getNumpyVersion` 方法获取张量的 NumPy 版本，然后使用 numpy.save 或 hdpy\u002Fpytables 保存您的 NumPy 数组。NumPy 保存更为轻量。\n\n## 需要帮助？\n\n您可以通过在 Gitter 上打开一个问题，或直接与我聊天：https:\u002F\u002Fgitter.im\u002FSpeedTorch。\n\n## 未来工作\n\n我正在考虑加入更多关于快速 CPU 到 GPU 数据传输的功能。如果您有任何想法，请在 GitHub 上提交一个问题。\n\n## 实验性功能\n\n除了 Cupy GPU\u002F固定在内存中的 CPU 张量以及 PyTorch CUDA 张量之外，SpeedTorch 还提供 PyTorch 固定在内存中的 CPU 张量和 Cupy memmap GPU\u002F固定在内存中的 CPU 张量。目前我尚未找到这些类型张量的实际用途，但它们已经完全实现并可供使用。\n\nhttps:\u002F\u002Fgithub.com\u002FSantosh-Gupta\u002FSpeedTorch\u002Ftree\u002Fmaster\u002FSpeedTorch\n\n我感兴趣的一个方向是探索是否可以通过使用 Cupy Memmaps 来减少内存占用。到目前为止，它们的内存占用与实时版本并无不同。\n\n## 文档\n\n### 类 ModelFactory\n\n```python\nModelFactory(model_variable,  total_classes,  embed_dimension, datatype = 'float32', CPUPinn = False)\n```\n\n使用 Cupy 为模型变量创建切换器。该切换器可以在完整的嵌入集合和模型批次集合之间切换变量。每个变量都需要一个独立的切换器。\n\n示例：\n\n```python\nuEmbed_switcher = SpeedTorch.ModelFactory( skip_gram_modelSparse.u_embeddings, total_classes=50000, embed_dimension=128)\n```\n\n参数：\n\n`model_variable`：您希望为其创建切换器的模型中的特定变量。\n\n`total_classes`：需要训练的嵌入总数。\n\n`embed_dimension`：嵌入的维度。\n\n`datatype`（可选）：变量的数据类型。默认为 'float32'。\n\n`CPUPinn`（可选）：将完整的嵌入集合固定在 CPU 上。这样可以节省 GPU 内存，但数据传输会变慢。默认为 False。\n\n方法：\n\n`zerosInit()`：将变量切换器的完整集合初始化为零。\n\n`uniformDistributionInit(low, high)`：将变量切换器的完整集合初始化为从 `low` 到 `high` 的均匀分布。\n\n`normalDistributionInit(mean, stdDev)`：将变量切换器的完整集合初始化为均值为 `mean`、标准差为 `stdDev` 的正态分布。\n\n`variableTransformer( batchSize, posPerBatch,  negPerBatch = None )`：设置用于模型前向传播步骤的占位输入。`batchSize` 是批次大小，`posPerBatch` 是每批次的正样本数量。如果还需要用于负样本的第二个占位输入，则可以将 `negPerBatch`（可选）设置为负样本数量，此时将返回两个占位输入，而不是一个。\n\n`beforeForwardPass(retrievedPosIndexes , retrievedNegIndexes = None)`：将嵌入从完整嵌入集合切换到模型嵌入集合。`retrievedPosIndexes` 是要检索的正样本索引。如果也需要检索负样本，则可以传递 `retrievedNegIndexes`（可选）作为负样本索引。\n\n`afterOptimizerStep( retrievedPosIndexes , retrievedNegIndexes = None)`：将更新后的嵌入从模型切换回完整嵌入集合。`retrievedPosIndexes` 是之前检索的正样本索引。如果也检索了负样本，则可以传递 `retrievedNegIndexes`（可选）作为负样本索引。\n\n`saveCupy(saveFileName)`：将张量保存为 .npy 文件。\n\n`loadCupy(loadFileName)`：从 .npy 文件加载张量。\n\n`getNumpyVersion`：获取张量的 NumPy 版本。\n\n### 类 OptimizerFactory\n\n```pyton\nOptimizerFactory( given_optimizer,  total_classes,  embed_dimension, model, variable_name, dtype='float32' , CPUPinn = False)\n```\n\n使用 Cupy 为优化器变量创建切换器。该切换器可以在完整的嵌入集合和优化器批次集合之间切换变量。每个变量都需要一个独立的切换器。\n\n示例：\n\n```python\nuAdagrad_switcher = SpeedTorch.OptimizerFactory(given_optimizer,  total_classes,  embed_dimension, model, variable_name, dtype='float32', CPUPinn = False)\n```\n\n参数：\n\n`given_optimizer`：已用您的模型权重初始化的优化器。如果用于嵌入训练，请确保将 `sparse` 参数设置为 `False`。目前支持的优化器包括 SparseAdam、Adadelta、Adamax、Adam、AdamW、ASGD 和 RMSprop。Rprop 也被支持，但需要先完成第一次前向传播和 `loss.backward()` 步骤，才能初始化 OptimizerFactory 实例。这是因为 Rprop 优化器需要其参数的梯度来进行初始化。\n\n`total_classes`：需要训练的嵌入总数。\n\n`embed_dimension`：嵌入的维度。\n\n`model`：您的模型实例。\n\n`variable_name`：模型中定义的变量的确切名称。\n\n`dtype`（可选）：您的变量的数据类型。默认为 'float32'。\n\n`CPUPinn`（可选）：将完整的优化器变量权重集合固定在 CPU 上。这样可以节省 GPU 内存，但数据传输会变慢。默认为 False。\n\n方法：\n\n`optInit`：初始化优化器变量切换器。\n\n`beforeForwardPass(retrievedPosIndexes , retrievedNegIndexes = None)`：将优化器变量权重从完整权重集合切换到优化器权重张量。`retrievedPosIndexes` 是要检索的正样本索引。如果也需要检索负样本，则可以传递 `retrievedNegIndexes`（可选）作为负样本索引。\n\n`afterOptimizerStep( retrievedPosIndexes , retrievedNegIndexes = None)`：将优化器变量权重从您的优化器切换回完整权重集合。`retrievedPosIndexes` 是之前检索的正样本索引。如果也检索了负样本，则可以传递 `retrievedNegIndexes`（可选）作为负样本索引。\n\n### 类 DataGadget\n\n创建一个张量，其主要功能是将其内容传输到 PyTorch 的 CUDA 变量中。\n\n```pyton\nDataGadget( fileName, CPUPinn=False)\n```\n\n参数：\n\n`fileName`：要打开的 .npy 数据文件的位置。\n\n`CPUPinn`（可选）：将您的数据固定在 CPU 上。默认为 False。\n\n方法：\n\n`getData(indexes)`：以 PyTorch Cuda 变量可以接受的格式检索数据。`indexes` 是要从中检索数据的张量索引。\n\n`insertData(dataObject, indexes)`：从 PyTorch Cuda 变量中插入数据。`dataObject` 是要从中提取数据的 PyTorch Cuda 变量张量，`indexes` 是要从中检索数据的张量索引。\n\n`saveCupy(saveFileName)`：将张量保存为 .npy 文件。\n\n`loadCupy(loadFileName)`：从 .npy 文件加载新的张量。\n\n`getNumpyVersion`：获取张量的 NumPy 版本。\n\n请参阅此笔记本，了解如何使用数据工具：\n\nhttps:\u002F\u002Fcolab.research.google.com\u002Fdrive\u002F185Z5Gi62AZxh-EeMfrTtjqxEifHOBXxF\n\n### PytorchModelFactory 类\n\n```python\nPytorchModelFactory(model_variable,  total_classes,  embed_dimension, datatype = 'float32', deviceType = 'cuda', pinType = False)\n```\n\n使用 PyTorch 张量为模型变量创建切换器。该切换器可以在完整的嵌入集合和模型批次集合之间切换变量。每个变量都需要一个独立的切换器。\n\n示例：\n\n```python\nuEmbed_switcher = SpeedTorch.PytorchModelFactory( skip_gram_modelSparse.u_embeddings, total_classes=50000, embed_dimension=128)\n```\n\n参数：\n\n`model_variable`：您希望为其创建切换器的模型中的特定变量。\n\n`total_classes`：需要训练的嵌入总数。\n\n`embed_dimension`：嵌入的维度。\n\n`datatype`（可选）：变量的数据类型。默认为 `'float32'`。\n\n`deviceType`（可选）：设备类型，可设置为 `'cuda'` 或 `'cpu'`。默认为 `'cuda'`。\n\n`pinType`（可选）：如果设备设置为 `'cpu'`，可以指定使用固定内存。默认为 `False`。\n\n\n方法：\n\n`zerosInit()`：将变量切换器的完整集合初始化为零。\n\n`uniformDistributionInit(low, high)`：将变量切换器的完整集合初始化为从 `low` 到 `high` 的均匀分布。\n\n`normalDistributionInit(mean, stdDev)`：将变量切换器的完整集合初始化为均值为 `mean`、标准差为 `stdDev` 的正态分布。\n\n`customInit(initFunction, *args)`：为变量切换器的完整集合使用任何 PyTorch 初始化器。通过 `initFunction` 传递初始化器，并通过 `*args` 传递其相应参数。\n\n`variableTransformer(batchSize, posPerBatch,  negPerBatch = None )`：设置用于模型前向传播步骤的占位输入。`batchSize` 是批次大小，`posPerBatch` 是每批次的正样本数量。如果还需要用于负样本的第二个占位输入，则可以将 `negPerBatch`（可选）设置为负样本数量，此时将返回两个占位输入，而不是一个。\n\n`beforeForwardPass(retrievedPosIndexes , retrievedNegIndexes = None)`：将嵌入从完整嵌入集合切换到模型嵌入集合。`retrievedPosIndexes` 是要检索的正样本索引。如果也需要检索负样本，则可以同时传递 `retrievedNegIndexes`（可选）。\n\n`afterOptimizerStep(retrievedPosIndexes , retrievedNegIndexes = None)`：将更新后的嵌入从模型切换回完整嵌入集合。`retrievedPosIndexes` 是已检索的正样本索引。如果也检索了负样本，则可以同时传递 `retrievedNegIndexes`（可选）。\n\n`saveTorch(saveFileName)`：使用 `torch.save` 将张量保存到文件。\n\n`loadTorch(loadFileName)`：使用 `torch.load` 加载张量。\n\n`getNumpyVersion`：获取张量的 NumPy 版本。 \n\n### PytorchOptimizerFactory 类\n\n```pyton\nPytorchOptimizerFactory( given_optimizer,  total_classes,  embed_dimension, model, variable_name, dtype='float32', deviceType = 'cuda', pinType = False)\n```\n\n使用 PyTorch 张量为优化器变量创建切换器。该切换器可以在完整的嵌入集合和优化器批次集合之间切换变量。每个变量都需要一个独立的切换器。\n\n示例：\n\n```python\nuAdagrad_switcher = SpeedTorch.PytorchOptimizerFactory(given_optimizer,  total_classes,  embed_dimension, model, variable_name, dtype='float32')\n```\n\n参数：\n\n`given_optimizer`：使用模型权重初始化的优化器。如果用于嵌入训练，请确保将 `sparse` 参数设置为 `False`。目前支持的优化器包括 SparseAdam、Adadelta、Adamax、Adam、AdamW、ASGD 和 RMSprop。Rprop 也被包含在内，但需要先完成第一次前向传播和 `loss.backward()` 步骤，才能初始化 OptimizerFactory 实例。这是因为 Rprop 优化器需要其参数的梯度来进行初始化。\n\n`total_classes`：需要训练的嵌入总数。\n\n`embed_dimension`：嵌入的维度。\n\n`model`：您的模型实例。\n\n`variable_name`：模型中定义的变量的确切名称。\n\n`dtype`（可选）：变量的数据类型。默认为 `'float32'`。\n\n`deviceType`（可选）：设备类型，可设置为 `'cuda'` 或 `'cpu'`。默认为 `'cuda'`。\n\n`pinType`（可选）：如果设备设置为 `'cpu'`，可以指定使用固定内存。默认为 `False`。\n\n\n方法：\n\n`optInit`：初始化优化器变量切换器。\n\n`beforeForwardPass(retrievedPosIndexes , retrievedNegIndexes = None)`：将优化器变量权重从完整权重集合切换到优化器权重张量。`retrievedPosIndexes` 是要检索的正样本索引。如果也需要检索负样本，则可以同时传递 `retrievedNegIndexes`（可选）。\n\n`afterOptimizerStep( retrievedPosIndexes , retrievedNegIndexes = None)`：将优化器变量权重从优化器切换回完整权重集合。`retrievedPosIndexes` 是已检索的正样本索引。如果也检索了负样本，则可以同时传递 `retrievedNegIndexes`（可选）。\n\n## 引用 SpeedTorch：\n如果您在研究中使用 SpeedTorch 或希望引用，请使用以下格式：\n\n@misc{\n\n  title={SpeedTorch},\n  \n  author={Santosh Gupta},\n  \n  howpublished={\\url{github.com\u002FSantosh-Gupta\u002FSpeedTorch}},\n  \n  year={2019}\n  \n}","# SpeedTorch 快速上手指南\n\nSpeedTorch 是一个旨在加速 PyTorch 中 CPU 与 GPU 之间张量传输的开源库。它利用 Cupy 的固定内存（Pinned Memory）技术，在特定场景下（尤其是 CPU 核心数较少时）能显著提升数据加载和稀疏嵌入训练的速度，并支持使用非稀疏优化器进行大规模嵌入训练。\n\n## 环境准备\n\n在使用 SpeedTorch 之前，请确保您的开发环境满足以下要求：\n\n*   **操作系统**：Linux (推荐) 或 Windows (需配置 CUDA 环境)。\n*   **Python 版本**：建议 Python 3.6+。\n*   **前置依赖**：\n    *   **PyTorch**：已安装并可用。\n    *   **CuPy**：**必须**先于 SpeedTorch 安装。CuPy 需要与您的系统 CUDA 版本匹配。\n    *   **GPU 驱动**：已正确安装 NVIDIA 驱动和 CUDA Toolkit。\n\n> **注意**：SpeedTorch 的核心加速原理依赖于 CuPy 的索引内核优化。如果您的系统拥有较多 CPU 核心（如 8 核以上），原生 PyTorch 的索引效率可能会提升，此时 SpeedTorch 的相对优势可能减弱，但仍建议在您的具体数据规模下进行基准测试。\n\n## 安装步骤\n\n请严格按照以下顺序执行安装命令。**必须先安装 CuPy，再安装 SpeedTorch**。\n\n### 1. 安装 CuPy\n根据您的 CUDA 版本选择对应的 CuPy 安装命令。以下是通用安装方式（自动检测 CUDA 版本）：\n\n```bash\npip install cupy-cuda11x\n# 如果是 CUDA 12.x，请使用: pip install cupy-cuda12x\n# 如果是旧版 CUDA 10.x，请使用: pip install cupy-cuda102\n```\n\n*国内用户加速建议*：如果下载缓慢，可指定清华或阿里镜像源：\n```bash\npip install cupy-cuda11x -i https:\u002F\u002Fpypi.tuna.tsinghua.edu.cn\u002Fsimple\n```\n\n### 2. 安装 SpeedTorch\n\n```bash\npip install SpeedTorch\n```\n\n*国内用户加速建议*：\n```bash\npip install SpeedTorch -i https:\u002F\u002Fpypi.tuna.tsinghua.edu.cn\u002Fsimple\n```\n\n### 3. 验证安装\n在 Python 环境中导入库，确保无报错：\n\n```python\nimport cupy\nimport SpeedTorch\nprint(\"SpeedTorch 安装成功！\")\n```\n\n## 基本使用\n\nSpeedTorch 的主要用途是加速数据传输以及支持使用常规优化器（如 Adam, Adamax 等）进行稀疏嵌入训练。\n\n### 场景一：加速 CPU 到 GPU 的数据传输\n\n使用 SpeedTorch 的 `DataGadget` 可以快速将数据从 CPU 加载到 GPU。\n\n```python\nimport torch\nimport cupy\nimport SpeedTorch\n\n# 初始化 SpeedTorch\n# 这一步会设置相关的后端配置\nSpeedTorch.init()\n\n# 假设你有一个大型数据集在 CPU 上\n# 创建示例数据 (100 万行，128 维)\ncpu_data = torch.randn(1000000, 128)\n\n# 使用 SpeedTorch 将数据转换为可在 GPU 高效访问的形式\n# 这里演示将数据移至 GPU 并进行操作\ngpu_tensor = SpeedTorch.to_cuda(cpu_data)\n\n# 现在 gpu_tensor 可以用于后续的 PyTorch 模型训练\n# 当需要传回 CPU 时，速度也会显著快于原生 PyTorch\ncpu_result = SpeedTorch.to_cpu(gpu_tensor)\n```\n\n### 场景二：使用非稀疏优化器训练大规模 Embedding\n\n这是 SpeedTorch 最核心的功能之一。它允许你将巨大的 Embedding 表存放在 CPU 内存中（节省显存），仅在需要时快速传输到 GPU，从而可以使用 `Adam`, `Adamax`, `RMSprop` 等不支持原生稀疏更新的优化器。\n\n```python\nimport torch\nimport torch.nn as nn\nimport SpeedTorch\nfrom SpeedTorch import PytorchModelFactory, PytorchOptimizerFactory\n\n# 1. 定义模型工厂\n# 指定设备：'cpu' (使用固定内存以加速传输) 或 'cuda'\n# pinned=True 表示启用 CPU 固定内存加速\nmodel_factory = PytorchModelFactory(device='cpu', pinned=True)\n\n# 2. 创建 Embedding 层\n# num_embeddings: 词表大小 (可以非常大，受限于 CPU 内存而非显存)\n# embedding_dim: 嵌入维度\nembedding_layer = model_factory.create_embedding(num_embeddings=10000000, embedding_dim=128)\n\n# 3. 定义优化器工厂\n# 现在可以使用任意优化器，例如 Adamax，即使是在做稀疏训练\noptimizer_factory = PytorchOptimizerFactory(device='cpu', pinned=True)\noptimizer = optimizer_factory.create_optimizer(optimizer_class=torch.optim.Adamax, \n                                               params=embedding_layer.parameters(), \n                                               lr=0.01)\n\n# 4. 训练循环示例\n# 假设 input_indices 是当前的批次数据 (位于 CPU 或 GPU 均可，SpeedTorch 会自动处理高效传输)\ninput_indices = torch.randint(0, 10000000, (32,)) \n\n# 前向传播 (SpeedTorch 会自动处理必要的 CPU\u003C->GPU 传输)\noutput = embedding_layer(input_indices)\n\n# 计算损失 (示例)\nloss = output.sum()\n\n# 反向传播与更新\nloss.backward()\noptimizer.step()\noptimizer.zero_grad()\n\nprint(\"使用 SpeedTorch + Adamax 完成了一步稀疏训练更新。\")\n```\n\n### 关键提示\n*   **内存权衡**：SpeedTorch 的 CuPy 固定内存张量比原生 PyTorch 张量占用更多内存，但换来了更快的传输速度。\n*   **适用场景**：最适合 CPU 核心数较少（如 2-4 核）且需要处理超大规模 Embedding 表的场景。\n*   **稀疏标志**：在使用上述工厂类创建模型时，由于参数会在每一步都被更新（通过快速传输机制），通常可以将相关参数视为稠密更新处理，从而解锁更多优化器选项。","某推荐系统团队正在训练包含数亿用户嵌入向量的大型模型，受限于显存容量，不得不将部分参数卸载到 CPU 内存中动态调度。\n\n### 没有 SpeedTorch 时\n- **显存瓶颈严重**：由于无法高效利用 CPU 内存，团队被迫缩小嵌入层维度或减少批量大小，导致模型表达能力受限，推荐准确率难以提升。\n- **数据传输延迟高**：在稀疏训练过程中，频繁将闲置参数从 CPU 换入 GPU 时，原生 PyTorch 的 pinned memory 传输速度较慢，成为训练流水线的最大堵点。\n- **优化器选择受限**：受限于稀疏梯度更新机制，只能使用 SGD 或 Adagrad 等基础优化器，无法启用 AdamW 或 RMSprop 等更先进的算法，收敛速度慢且效果不佳。\n- **硬件资源浪费**：大容量 CPU 内存处于闲置状态，而昂贵的 GPU 显存却时刻告急，造成算力与存储资源的严重错配。\n\n### 使用 SpeedTorch 后\n- **突破显存限制**：借助 SpeedTorch 将海量闲置嵌入向量托管在 CPU RAM 中，仅在计算时快速加载，成功在单卡上训练了原本需要多卡并行的超大规模模型。\n- **传输效率飞跃**：利用其基于 Cupy 的固定内存技术，CPU 到 GPU 的数据传输速度提升约 3.1 倍，反向传输更是快了 410 倍，彻底消除了数据搬运带来的等待时间。\n- **解锁高级优化器**：高效的传输机制使得在稀疏嵌入训练中直接使用 AdamW、Adamax 等复杂优化器成为可能，显著加快了模型收敛速度并提升了最终指标。\n- **资源利用率最大化**：完美协同 CPU 大内存与 GPU 高算力，让每一分硬件投入都转化为实际的训练吞吐量，大幅降低了单位样本的训练成本。\n\nSpeedTorch 通过极致的数据传输优化，打破了显存墙的限制，让开发者能够以更低的成本训练更大、更强的深度学习模型。","https:\u002F\u002Foss.gittoolsai.com\u002Fimages\u002FSantosh-Gupta_SpeedTorch_2ede607b.png","Santosh-Gupta","Santosh Gupta","https:\u002F\u002Foss.gittoolsai.com\u002Favatars\u002FSantosh-Gupta_75c3de70.jpg","Machine learning\u002FNLP for scientific\u002Fmedical information retrieval ",null,"Fremont, CA","San.Gupta.ML@gmail.com","https:\u002F\u002Fgithub.com\u002FSantosh-Gupta",[82],{"name":83,"color":84,"percentage":85},"Python","#3572A5",100,683,40,"2025-11-13T01:53:37","MIT","未说明","需要 NVIDIA GPU（测试环境为 Tesla K80），需安装支持 GPU 的 CuPy 版本","取决于模型大小；利用 CPU 内存存储嵌入参数以节省显存，核心优势在于可使用大量 CPU RAM",{"notes":94,"python":90,"dependencies":95},"1. 必须先安装并导入 CuPy，然后才能导入 SpeedTorch。\n2. 该库主要利用 CuPy 的 pinned CPU 张量来实现比原生 PyTorch 更快的 CPU-GPU 数据传输（特别是在 CPU 核心数较少如 2 核时）。\n3. 适用于需要训练大量嵌入（embeddings）且显存不足的场景，可将闲置参数存储在 CPU 内存中。\n4. 在 CPU 核心数较多（如 4 核以上）的系统上，速度优势可能会减弱。\n5. 提供了兼容非稀疏优化器（如 Adam, Adamax 等）进行稀疏训练的功能。",[96,97],"cupy","torch",[16,14,35],[100,101,102,103,96,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118],"cpu-pinned-tensors","pytorch-variables","gpu-transfer","cuda-variables","data-transfer","pytorch-tensors","cuda-tensors","embeddings-trained","pytorch","embeddings","cuda","sparse","sparse-modeling","machine-learning","natural-language-processing","nlp","gpu","cpu-gpu-transfer","pinned-cpu-tensors","2026-03-27T02:49:30.150509","2026-04-10T15:53:37.961239",[122,127,132],{"id":123,"question_zh":124,"answer_zh":125,"source_url":126},27737,"如何使用 SpeedTorch 加速 PyTorch GPU Tensor 到 CPU 的转换？","可以通过以下步骤使用 SpeedTorch 的 DataGadget 进行加速：\n1. 准备数据并保存为 .npy 文件。\n2. 初始化 SpeedTorch.DataGadget 并调用 gadgetInit()。\n3. 同步 CUDA 和 CuPy 设备。\n4. 在 torch.no_grad() 上下文中，使用 insertData 将 Tensor 数据插入 Gadget。\n5. 使用 cupy.asnumpy() 获取最终结果。\n\n示例代码：\n```python\noutput_cudatorch = torch.squeeze(inference_output).data\nh, w = output_cudatorch.shape\nsampl = np.random.uniform(low=0.0, high=192.0, size=(h, w)).astype(np.float32)\nnp.save('data.npy', sampl)\ndel sampl\ngadgetGPU = SpeedTorch.DataGadget('data.npy')\ngadgetGPU.gadgetInit()\ntorch.cuda.synchronize()\ncupy.cuda.Device().synchronize()\nwith torch.no_grad():\n    gadgetGPU.insertData(dataObject=output_cudatorch[:,:], indexes=(slice(0,h), slice(0,w)))\n    output = cupy.asnumpy(gadgetGPU.CUPYcorpus[:, :])\ncupy.cuda.Device().synchronize()\ntorch.cuda.synchronize()\n```\n注意：如果数据量较小（如 640*400），加速效果可能不明显，甚至与原生的 `.cpu().numpy()` 耗时相同。建议参考官方 Colab 基准测试对比不同数据量下的性能。","https:\u002F\u002Fgithub.com\u002FSantosh-Gupta\u002FSpeedTorch\u002Fissues\u002F8",{"id":128,"question_zh":129,"answer_zh":130,"source_url":131},27738,"在哪里可以找到 SpeedTorch 的基准测试（Benchmarking）代码？","基准测试代码位于 Google Colab 笔记本中，您可以直接访问以下链接运行测试：\nhttps:\u002F\u002Fcolab.research.google.com\u002Fdrive\u002F1PXhbmBZqtiq_NlfgUIaNpf_MfpiQSKKs\n建议在运行前修改数据量以匹配您实际应用中的数据处理规模，以便准确评估速度优势。","https:\u002F\u002Fgithub.com\u002FSantosh-Gupta\u002FSpeedTorch\u002Fissues\u002F5",{"id":133,"question_zh":134,"answer_zh":135,"source_url":126},27739,"为什么使用 SpeedTorch 后数据传输时间没有减少？","如果在小数据量（例如 640*400 的 float32 矩阵）下测试，SpeedTorch 的开销可能导致其运行时间与原生 PyTorch 方法（`tensor.cpu().numpy()`）相当甚至更慢。此外，统计耗时的方法也可能影响结果准确性。建议：\n1. 检查计时方法是否正确（确保排除初始化等非传输时间）。\n2. 增加数据量进行测试，SpeedTorch 通常在大数据传输场景下优势更明显。\n3. 参考官方 Colab 示例，其中复制大小为 131072 的数据仅需约 3ms，而较大尺寸数据才能体现优化效果。",[]]