{"id":490250,"date":"2026-08-08T12:15:39","date_gmt":"2026-08-08T12:15:39","guid":{"rendered":"https:\/\/savepearlharbor.com\/?p=490250"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=490250","title":{"rendered":"\u041f\u043e\u0431\u0435\u0436\u0434\u0430\u0435\u043c OOM \u0432 PyTorch: \u043a\u0430\u043a \u043e\u0431\u0443\u0447\u0430\u0442\u044c \u0433\u0438\u0433\u0430\u043d\u0442\u0441\u043a\u0438\u0435 \u0433\u0440\u0430\u0444\u044b \u043d\u0430 \u043e\u0431\u044b\u0447\u043d\u043e\u0439 \u0432\u0438\u0434\u0435\u043e\u043a\u0430\u0440\u0442\u0435"},"content":{"rendered":"<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u0415\u0441\u043b\u0438 \u0432\u044b \u043e\u0431\u0443\u0447\u0430\u0435\u0442\u0435 \u0433\u0440\u0430\u0444\u043d\u044b\u0435 \u043d\u0435\u0439\u0440\u043e\u0441\u0435\u0442\u0438  \u0438\u043b\u0438 Knowledge Graph Embeddings \u043d\u0430 \u043c\u0438\u043b\u043b\u0438\u043e\u043d\u044b \u0443\u0437\u043b\u043e\u0432, \u0432\u044b \u043d\u0430\u0432\u0435\u0440\u043d\u044f\u043a\u0430 \u0441\u0442\u0430\u043b\u043a\u0438\u0432\u0430\u043b\u0438\u0441\u044c \u0441 \u0442\u0435\u043c, \u0447\u0442\u043e \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0439 <code>torch.optim.SparseAdam<\/code> \u043c\u043e\u043c\u0435\u043d\u0442\u0430\u043b\u044c\u043d\u043e \u0437\u0430\u0431\u0438\u0432\u0430\u0435\u0442 \u0432\u0441\u044e \u043e\u043f\u0435\u0440\u0430\u0442\u0438\u0432\u043d\u0443\u044e \u043f\u0430\u043c\u044f\u0442\u044c  \u0438\u043b\u0438 \u0432\u0438\u0434\u0435\u043e\u043f\u0430\u043c\u044f\u0442\u044c.<\/p>\n<p>\u042f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0430\u043b \u043c\u0430\u043b\u0435\u043d\u044c\u043a\u0438\u0439 \u043f\u0430\u043a\u0435\u0442 <a href=\"https:\/\/github.com\/Assistentus\/DSA\" rel=\"noopener noreferrer nofollow\"><strong>Disk Sparse Adam (DSA)<\/strong><\/a> \u2014 Out-of-Core \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0442\u043e\u0440 \u0434\u043b\u044f PyTorch, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u044b\u043d\u043e\u0441\u0438\u0442 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u043c\u043e\u043c\u0435\u043d\u0442\u043e\u0432 (<img decoding=\"async\" class=\"formula inline\" source=\"m\" alt=\"m\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/formulas\/6\/6f\/6f8\/6f8f57715090da2632453988d9a1501b.svg\" width=\"16\" height=\"12\" data-width=\"1.986\" data-height=\"1.025\" data-vertical-align=\"-0.025\" style=\"width: 1.986ex; height: 1.025ex; vertical-align: -0.025ex\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/getpro\/habr\/formulas\/6\/6f\/6f8\/6f8f57715090da2632453988d9a1501b.svg 780w,&#10;       https:\/\/habrastorage.org\/getpro\/habr\/formulas\/6\/6f\/6f8\/6f8f57715090da2632453988d9a1501b.svg 781w\" loading=\"lazy\" decode=\"async\"\/> \u0438 <img decoding=\"async\" class=\"formula inline\" source=\"v\" alt=\"v\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/formulas\/9\/9e\/9e3\/9e3669d19b675bd57058fd4664205d2a.svg\" width=\"12\" height=\"12\" data-width=\"1.097\" data-height=\"1.027\" data-vertical-align=\"-0.025\" style=\"width: 1.097ex; height: 1.027ex; vertical-align: -0.025ex\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/getpro\/habr\/formulas\/9\/9e\/9e3\/9e3669d19b675bd57058fd4664205d2a.svg 780w,&#10;       https:\/\/habrastorage.org\/getpro\/habr\/formulas\/9\/9e\/9e3\/9e3669d19b675bd57058fd4664205d2a.svg 781w\" loading=\"lazy\" decode=\"async\"\/>) \u043d\u0430 \u0434\u0438\u0441\u043a \u0447\u0435\u0440\u0435\u0437 <code>mmap<\/code>. \u042d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043e\u0431\u0443\u0447\u0430\u0442\u044c \u043e\u0433\u0440\u043e\u043c\u043d\u044b\u0435 \u0441\u043f\u0430\u0440\u0441-\u043c\u043e\u0434\u0435\u043b\u0438 \u043d\u0430 \u043e\u0431\u044b\u0447\u043d\u044b\u0445 \u043f\u043e\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0445 \u0432\u0438\u0434\u0435\u043e\u043a\u0430\u0440\u0442\u0430\u0445 (RTX 3090\/4090 \u0438\u043b\u0438 \u0434\u0430\u0436\u0435 \u0431\u0435\u0441\u043f\u043b\u0430\u0442\u043d\u043e\u043c Colab) \u043f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0431\u0435\u0437 \u0440\u0430\u0441\u0445\u043e\u0434\u0430 \u043f\u0430\u043c\u044f\u0442\u0438 \u043f\u043e\u0434 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0442\u043e\u0440.<\/p>\n<hr\/>\n<h4>\u0412 \u0447\u0435\u043c \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 \u0441\u043e \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u043c SparseAdam?<\/h4>\n<p>\u0417\u0430\u0434\u0430\u0447\u0430: \u043e\u0431\u0443\u0447\u0438\u0442\u044c \u043c\u043e\u0434\u0435\u043b\u044c \u0434\u043b\u044f Knowledge Graph \u043d\u0430 <strong>10 \u043c\u0438\u043b\u043b\u0438\u043e\u043d\u043e\u0432 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0435\u0439<\/strong> \u0441 \u0440\u0430\u0437\u043c\u0435\u0440\u043d\u043e\u0441\u0442\u044c\u044e \u0432\u0435\u043a\u0442\u043e\u0440\u0430 <code>128<\/code>.<\/p>\n<p>\u041f\u043e\u0441\u0447\u0438\u0442\u0430\u0435\u043c \u043f\u0430\u043c\u044f\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f \u0442\u0430\u0431\u043b\u0438\u0446\u044b \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 \u0432 float32:<\/p>\n<ul>\n<li>\n<p><strong>\u0421\u0430\u043c\u0438 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b (Weight):<\/strong> <code>10,000,000 * 128 * 4 \u0431\u0430\u0439\u0442\u0430 = ~5.12 \u0413\u0411<\/code><\/p>\n<\/li>\n<\/ul>\n<p>\u041a\u0430\u0437\u0430\u043b\u043e\u0441\u044c \u0431\u044b, 5 \u0413\u0411 \u043b\u0435\u0433\u043a\u043e \u0432\u043b\u0435\u0437\u0430\u044e\u0442 \u0432 \u043b\u044e\u0431\u0443\u044e \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e \u0432\u0438\u0434\u0435\u043e\u043a\u0430\u0440\u0442\u0443 \u0441 16\u201324 \u0413\u0411 VRAM \u0438\u043b\u0438 \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u0443\u044e RAM. \u041d\u043e \u043a\u0430\u043a \u0442\u043e\u043b\u044c\u043a\u043e \u043c\u044b \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u043c \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0439 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0442\u043e\u0440 <code>torch.optim.SparseAdam<\/code>, \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b:<\/p>\n<ul>\n<li>\n<p><strong>\u041f\u0435\u0440\u0432\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 (<img decoding=\"async\" class=\"formula inline\" source=\"m\" alt=\"m\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/formulas\/6\/6f\/6f8\/6f8f57715090da2632453988d9a1501b.svg\" width=\"16\" height=\"12\" data-width=\"1.986\" data-height=\"1.025\" data-vertical-align=\"-0.025\" style=\"width: 1.986ex; height: 1.025ex; vertical-align: -0.025ex\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/getpro\/habr\/formulas\/6\/6f\/6f8\/6f8f57715090da2632453988d9a1501b.svg 780w,&#10;       https:\/\/habrastorage.org\/getpro\/habr\/formulas\/6\/6f\/6f8\/6f8f57715090da2632453988d9a1501b.svg 781w\" loading=\"lazy\" decode=\"async\"\/>):<\/strong> \u0435\u0449\u0435 <strong>5.12 \u0413\u0411<\/strong><\/p>\n<\/li>\n<li>\n<p><strong>\u0412\u0442\u043e\u0440\u043e\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 (<img decoding=\"async\" class=\"formula inline\" source=\"v\" alt=\"v\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/formulas\/9\/9e\/9e3\/9e3669d19b675bd57058fd4664205d2a.svg\" width=\"12\" height=\"12\" data-width=\"1.097\" data-height=\"1.027\" data-vertical-align=\"-0.025\" style=\"width: 1.097ex; height: 1.027ex; vertical-align: -0.025ex\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/getpro\/habr\/formulas\/9\/9e\/9e3\/9e3669d19b675bd57058fd4664205d2a.svg 780w,&#10;       https:\/\/habrastorage.org\/getpro\/habr\/formulas\/9\/9e\/9e3\/9e3669d19b675bd57058fd4664205d2a.svg 781w\" loading=\"lazy\" decode=\"async\"\/>):<\/strong> \u0435\u0449\u0435 <strong>5.12 \u0413\u0411<\/strong><\/p>\n<\/li>\n<\/ul>\n<p>\u0418\u0442\u043e\u0433\u043e \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0442\u043e\u0440 \u00ab\u043d\u0430 \u0440\u043e\u0432\u043d\u043e\u043c \u043c\u0435\u0441\u0442\u0435\u00bb \u0437\u0430\u0431\u0438\u0440\u0430\u0435\u0442 <strong>10.24 \u0413\u0411<\/strong> \u043f\u0430\u043c\u044f\u0442\u0438 \u043f\u043e\u0434 \u0438\u0441\u0442\u043e\u0440\u0438\u044e \u0433\u0440\u0430\u0434\u0438\u0435\u043d\u0442\u043e\u0432. \u0415\u0441\u043b\u0438 \u0443\u0432\u0435\u043b\u0438\u0447\u0438\u0442\u044c \u0440\u0430\u0437\u043c\u0435\u0440\u043d\u043e\u0441\u0442\u044c \u0434\u043e 256 \u0438\u043b\u0438 \u0432\u0437\u044f\u0442\u044c \u0433\u0440\u0430\u0444 \u043d\u0430 50 \u043c\u043b\u043d \u0443\u0437\u043b\u043e\u0432 \u2014 \u043f\u0430\u043c\u044f\u0442\u044c \u043c\u043e\u043c\u0435\u043d\u0442\u0430\u043b\u044c\u043d\u043e \u0437\u0430\u043a\u0430\u043d\u0447\u0438\u0432\u0430\u0435\u0442\u0441\u044f, \u0438 PyTorch \u043f\u0430\u0434\u0430\u0435\u0442 \u0441 \u043a\u043b\u0430\u0441\u0441\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u043e\u0448\u0438\u0431\u043a\u043e\u0439:<\/p>\n<pre><code>CUDA out of memory. Tried to allocate X.XX GiB...<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:87px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0438\u043b\u0438 \u0441\u0438\u0441\u0442\u0435\u043c\u0430 \u00ab\u043d\u0430\u043c\u0435\u0440\u0442\u0432\u043e\u00bb \u0432\u0435\u0448\u0430\u0435\u0442 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u0443\u044e \u0441\u0438\u0441\u0442\u0435\u043c\u0443, \u0437\u0430\u043f\u043e\u043b\u043d\u044f\u044f \u0432\u0435\u0441\u044c SWAP.<\/p>\n<pre><code>\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\u2502              \u041f\u0430\u043c\u044f\u0442\u044c \u043f\u0440\u0438 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u043c SparseAdam           \u2502\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\u2502 [\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b: 5.12 \u0413\u0411] + [m-state: 5.12 \u0413\u0411] + [v-state: 5.12 \u0413\u0411]   \u2502 = ~15.36 \u0413\u0411 (\u0417\u0430\u0431\u0438\u0432\u0430\u0435\u0442 VRAM\/RAM \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e)                \u2502\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<hr\/>\n<h4>\u0418\u0434\u0435\u044f: Out-of-Core \u0438 Memory Mapping (mmap)<\/h4>\n<p>\u0412 \u0447\u0435\u043c \u043a\u043b\u044e\u0447\u0435\u0432\u0430\u044f \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0441\u0442\u044c <strong>\u0440\u0430\u0437\u0440\u0435\u0436\u0435\u043d\u043d\u043e\u0433\u043e (Sparse)<\/strong> \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f? \u0412 \u043a\u0430\u0436\u0434\u043e\u043c \u043c\u0438\u043d\u0438-\u0431\u0430\u0442\u0447\u0435 \u043c\u044b \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u043c <strong>\u043d\u0435 \u0432\u0441\u0435 10 \u043c\u0438\u043b\u043b\u0438\u043e\u043d\u043e\u0432 \u0443\u0437\u043b\u043e\u0432<\/strong>, \u0430 \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0435 \u043f\u043e\u0434\u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, 10 000 \u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0445 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0435\u0439, \u043f\u043e\u043f\u0430\u0432\u0448\u0438\u0445 \u0432 \u0442\u0435\u043a\u0443\u0449\u0438\u0439 \u0431\u0430\u0442\u0447).<\/p>\n<p>\u0412\u043e\u0437\u043d\u0438\u043a\u0430\u0435\u0442 \u0432\u043e\u043f\u0440\u043e\u0441: <strong>\u0437\u0430\u0447\u0435\u043c \u0434\u0435\u0440\u0436\u0430\u0442\u044c \u0432 \u0434\u043e\u0440\u043e\u0433\u043e\u0439 \u043f\u0430\u043c\u044f\u0442\u0438 GPU\/RAM \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f <img decoding=\"async\" class=\"formula inline\" source=\"m\" alt=\"m\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/formulas\/6\/6f\/6f8\/6f8f57715090da2632453988d9a1501b.svg\" width=\"16\" height=\"12\" data-width=\"1.986\" data-height=\"1.025\" data-vertical-align=\"-0.025\" style=\"width: 1.986ex; height: 1.025ex; vertical-align: -0.025ex\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/getpro\/habr\/formulas\/6\/6f\/6f8\/6f8f57715090da2632453988d9a1501b.svg 780w,&#10;       https:\/\/habrastorage.org\/getpro\/habr\/formulas\/6\/6f\/6f8\/6f8f57715090da2632453988d9a1501b.svg 781w\" loading=\"lazy\" decode=\"async\"\/> \u0438 <img decoding=\"async\" class=\"formula inline\" source=\"v\" alt=\"v\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/formulas\/9\/9e\/9e3\/9e3669d19b675bd57058fd4664205d2a.svg\" width=\"12\" height=\"12\" data-width=\"1.097\" data-height=\"1.027\" data-vertical-align=\"-0.025\" style=\"width: 1.097ex; height: 1.027ex; vertical-align: -0.025ex\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/getpro\/habr\/formulas\/9\/9e\/9e3\/9e3669d19b675bd57058fd4664205d2a.svg 780w,&#10;       https:\/\/habrastorage.org\/getpro\/habr\/formulas\/9\/9e\/9e3\/9e3669d19b675bd57058fd4664205d2a.svg 781w\" loading=\"lazy\" decode=\"async\"\/> \u0434\u043b\u044f \u0432\u0441\u0435\u0445 10 \u043c\u043b\u043d \u0443\u0437\u043b\u043e\u0432 \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e, \u0435\u0441\u043b\u0438 \u043f\u0440\u044f\u043c\u043e \u0441\u0435\u0439\u0447\u0430\u0441 \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u044b \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f 10 000?<\/strong><\/p>\n<p>\u0422\u0430\u043a \u043f\u043e\u044f\u0432\u0438\u043b\u0441\u044f <strong>Disk Sparse Adam (DSA)<\/strong>.<\/p>\n<pre><code>\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\u2502              \u041f\u0430\u043c\u044f\u0442\u044c \u043f\u0440\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 DSA                \u2502\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\u2502 VRAM \/ RAM: [\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b + \u0410\u043a\u0442\u0438\u0432\u043d\u044b\u0439 \u0431\u0430\u0442\u0447 (\u043f\u0430\u0440\u0430 \u041c\u0411)]        \u2502\u2502 DISK (mmap): [\u0418\u0441\u0442\u043e\u0440\u0438\u044f m \u0438 v \u043b\u0435\u0436\u0438\u0442 \u043d\u0430 NVMe SSD]           \u2502\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>DSA \u0432\u044b\u043d\u043e\u0441\u0438\u0442 \u043c\u0430\u0442\u0440\u0438\u0446\u044b \u043c\u043e\u043c\u0435\u043d\u0442\u043e\u0432 <img decoding=\"async\" class=\"formula inline\" source=\"m\" alt=\"m\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/formulas\/6\/6f\/6f8\/6f8f57715090da2632453988d9a1501b.svg\" width=\"16\" height=\"12\" data-width=\"1.986\" data-height=\"1.025\" data-vertical-align=\"-0.025\" style=\"width: 1.986ex; height: 1.025ex; vertical-align: -0.025ex\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/getpro\/habr\/formulas\/6\/6f\/6f8\/6f8f57715090da2632453988d9a1501b.svg 780w,&#10;       https:\/\/habrastorage.org\/getpro\/habr\/formulas\/6\/6f\/6f8\/6f8f57715090da2632453988d9a1501b.svg 781w\" loading=\"lazy\" decode=\"async\"\/> \u0438 <img decoding=\"async\" class=\"formula inline\" source=\"v\" alt=\"v\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/formulas\/9\/9e\/9e3\/9e3669d19b675bd57058fd4664205d2a.svg\" width=\"12\" height=\"12\" data-width=\"1.097\" data-height=\"1.027\" data-vertical-align=\"-0.025\" style=\"width: 1.097ex; height: 1.027ex; vertical-align: -0.025ex\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/getpro\/habr\/formulas\/9\/9e\/9e3\/9e3669d19b675bd57058fd4664205d2a.svg 780w,&#10;       https:\/\/habrastorage.org\/getpro\/habr\/formulas\/9\/9e\/9e3\/9e3669d19b675bd57058fd4664205d2a.svg 781w\" loading=\"lazy\" decode=\"async\"\/> \u043d\u0430 \u0434\u0438\u0441\u043a \u0432 \u0432\u0438\u0434\u0435 \u0431\u0438\u043d\u0430\u0440\u043d\u044b\u0445 \u0444\u0430\u0439\u043b\u043e\u0432 \u0438 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0435\u0442 \u0438\u0445 \u0432 \u043f\u0430\u043c\u044f\u0442\u044c \u0447\u0435\u0440\u0435\u0437 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c OS <code><strong>mmap<\/strong><\/code><strong> (memory mapping)<\/strong>:<\/p>\n<ol>\n<li>\n<p>\u041d\u0430 \u0448\u0430\u0433\u0435 <code>optimizer.step()<\/code> DSA \u0441\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u0442 \u0441 \u0434\u0438\u0441\u043a\u0430 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u043c\u043e\u043c\u0435\u043d\u0442\u043e\u0432 <strong>\u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f \u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0445 \u0438\u043d\u0434\u0435\u043a\u0441\u043e\u0432<\/strong> \u0442\u0435\u043a\u0443\u0449\u0435\u0433\u043e \u0431\u0430\u0442\u0447\u0430.<\/p>\n<\/li>\n<li>\n<p>\u041f\u0440\u043e\u0432\u043e\u0434\u0438\u0442 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u043f\u043e \u0444\u043e\u0440\u043c\u0443\u043b\u0435 Adam.<\/p>\n<\/li>\n<li>\n<p>\u0417\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044b\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u043e\u0431\u0440\u0430\u0442\u043d\u043e \u043d\u0430 \u0434\u0438\u0441\u043a.<\/p>\n<\/li>\n<li>\n<p>\u0420\u0430\u0441\u0445\u043e\u0434 \u043e\u043f\u0435\u0440\u0430\u0442\u0438\u0432\u043d\u043e\u0439\/\u0432\u0438\u0434\u0435\u043e\u043f\u0430\u043c\u044f\u0442\u0438 \u043f\u043e\u0434 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0442\u043e\u0440\u0430 \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f <strong>\u043f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043d\u0443\u043b\u0435\u0432\u044b\u043c<\/strong>.<\/p>\n<\/li>\n<\/ol>\n<hr\/>\n<h4>\u041a\u0430\u043a \u044d\u0442\u043e \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0432 \u043a\u043e\u0434\u0435<\/h4>\n<p>\u041e\u0434\u043d\u0430 \u0438\u0437 \u0433\u043b\u0430\u0432\u043d\u044b\u0445 \u0437\u0430\u0434\u0430\u0447 \u043f\u0440\u0438 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435 DSA \u2014 \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0435\u0433\u043e <strong>Drop-in \u0437\u0430\u043c\u0435\u043d\u043e\u0439<\/strong> \u0434\u043b\u044f \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0445 \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d\u043e\u0432 PyTorch. \u0412\u0430\u043c \u043d\u0435 \u043d\u0443\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0443 \u043c\u043e\u0434\u0435\u043b\u0438 \u0438\u043b\u0438 \u0434\u0430\u0442\u0430\u043b\u043e\u0430\u0434\u0435\u0440\u044b.<\/p>\n<h3>\u0411\u044b\u043b\u043e (\u0421\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0439 PyTorch):<\/h3>\n<pre><code class=\"python\">import torchembedding = torch.nn.EmbeddingBag(10_000_000, 128, sparse=True)optimizer = torch.optim.SparseAdam(embedding.parameters(), lr=0.001)for batch_idx in dataloader:    optimizer.zero_grad()    out = embedding(batch_idx)    loss = compute_loss(out)    loss.backward()    optimizer.step()<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<h3>\u0421\u0442\u0430\u043b\u043e (\u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c DSA):<\/h3>\n<pre><code class=\"python\">import torchfrom dsa.optimizer import DiskSparseRiemannianAdam# \u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u043c \u044d\u043c\u0431\u0435\u0434\u0434\u0438\u043d\u0433\u0438embedding = torch.nn.Embedding(10_000_000, 128, sparse=True)# \u0423\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c \u043f\u0430\u043f\u043a\u0443 \u043d\u0430 \u0434\u0438\u0441\u043a\u0435 \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0439 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0442\u043e\u0440\u0430optimizer = DiskSparseRiemannianAdam(    params={\"emb\": embedding.weight},     lr=0.001,     k=0.0, # 0.0 \u2014 \u0415\u0432\u043a\u043b\u0438\u0434\u043e\u0432\u043e \u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0441\u0442\u0432\u043e, 1.0 \u2014 \u0428\u0430\u0440 \u041f\u0443\u0430\u043d\u043a\u0430\u0440\u0435 (\u0433\u0438\u043f\u0435\u0440\u0431\u043e\u043b\u0438\u0447\u0435\u0441\u043a\u043e\u0435)    disk_dir=\".\/opt_cache\")# \u0412 \u0446\u0438\u043a\u043b\u0435 \u043e\u0431\u0443\u0447\u0435\u043d\u0438\u044f \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u043c \u0433\u0440\u0430\u0434\u0438\u0435\u043d\u0442\u044bfor batch_indices in dataloader:    # \u0414\u043e\u0441\u0442\u0430\u0435\u043c \u0432\u0435\u0441\u0430 \u0431\u0430\u0442\u0447\u0430 \u0441 \u0434\u0438\u0441\u043a\u0430    idx_np = batch_indices.numpy()    weights_np = optimizer.state_files[\"emb\"][\"w\"][idx_np].copy()    current_weights = torch.from_numpy(weights_np).requires_grad_(True)        loss = compute_loss(current_weights)    loss.backward()        # \u041f\u0435\u0440\u0435\u0434\u0430\u0435\u043c \u0438\u043d\u0434\u0435\u043a\u0441\u044b \u0438 \u0433\u0440\u0430\u0434\u0438\u0435\u043d\u0442\u044b \u0432 DSA    optimizer.step(updates={\"emb\": (batch_indices, current_weights.grad)})# \u0424\u0438\u043d\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u043c \u0444\u043e\u043d\u043e\u0432\u044b\u0439 \u043f\u043e\u0442\u043e\u043a \u0437\u0430\u043f\u0438\u0441\u0438optimizer.shutdown()<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<hr\/>\n<h4>\u0421\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u0435 \u0438 \u041f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c<\/h4>\n<h3>1. \u041f\u043e\u0442\u0440\u0435\u0431\u043b\u0435\u043d\u0438\u0435 \u043f\u0430\u043c\u044f\u0442\u0438 (RAM \/ VRAM)<\/h3>\n<p>\u0421 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c DSA \u0440\u0430\u0441\u0445\u043e\u0434 \u043f\u0430\u043c\u044f\u0442\u0438 \u043f\u043e\u0434 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0442\u043e\u0440\u0430 \u0441\u043d\u0438\u0436\u0430\u0435\u0442\u0441\u044f \u043e\u0442 <strong>\u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u0433\u0438\u0433\u0430\u0431\u0430\u0439\u0442 \u0434\u043e\u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u043c\u0435\u0433\u0430\u0431\u0430\u0439\u0442<\/strong> (\u0437\u0430\u0432\u0438\u0441\u0438\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0442 \u0440\u0430\u0437\u043c\u0435\u0440\u0430 \u043c\u0438\u043d\u0438-\u0431\u0430\u0442\u0447\u0430). \u042d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043e\u0431\u0443\u0447\u0430\u0442\u044c \u043c\u043e\u0434\u0435\u043b\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0440\u0430\u043d\u044c\u0448\u0435 \u0432 \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u0435 \u043d\u0435 \u043f\u043e\u043c\u0435\u0449\u0430\u043b\u0438\u0441\u044c \u043d\u0430 \u0440\u0430\u0431\u043e\u0447\u0435\u0439 \u0441\u0442\u0430\u043d\u0446\u0438\u0438.<\/p>\n<h3>2. \u0421\u043a\u043e\u0440\u043e\u0441\u0442\u044c I\/O<\/h3>\n<p>\u041a\u043e\u043d\u0435\u0447\u043d\u043e \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u043e\u0431\u0443\u0447\u0435\u043d\u0438\u044f \u043d\u0435 \u0441\u0440\u0430\u0432\u043d\u0438\u0442\u0441\u044f \u0441 \u043e\u0431\u0443\u0447\u0435\u043d\u0438\u0435\u043c \u043d\u0430 GPU \u043d\u043e  \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0439 NVMe SSD \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0432\u0430\u0435\u0442 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u043e\u0433\u043e \u0447\u0442\u0435\u043d\u0438\u044f\/\u0437\u0430\u043f\u0438\u0441\u0438 \u0432 \u0434\u0435\u0441\u044f\u0442\u043a\u0438 \u0442\u044b\u0441\u044f\u0447 IOPS(\u043d\u0435 \u0438\u0437\u043c\u0435\u0440\u044f\u043b), \u0430 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u0430\u044f \u0441\u0438\u0441\u0442\u0435\u043c\u0430 \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e \u043a\u044d\u0448\u0438\u0440\u0443\u0435\u0442 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u0447\u0435\u0440\u0435\u0437 Page Cache, \u043d\u0430\u043a\u043b\u0430\u0434\u043d\u044b\u0435 \u0440\u0430\u0441\u0445\u043e\u0434\u044b \u043d\u0430 \u0434\u0438\u0441\u043a \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u044b \u0438 \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u043f\u0435\u0440\u0435\u043a\u0440\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u044d\u043a\u043e\u043d\u043e\u043c\u0438\u0435\u0439 \u043f\u0430\u043c\u044f\u0442\u0438.<\/p>\n<hr\/>\n<h4>\u0413\u0434\u0435 \u044d\u0442\u043e \u043f\u0440\u0438\u0433\u043e\u0434\u0438\u0442\u0441\u044f?<\/h4>\n<ol>\n<li>\n<p><strong>GNN \u0438 \u0433\u0440\u0430\u0444\u043d\u044b\u0435 \u043d\u0435\u0439\u0440\u043e\u0441\u0435\u0442\u0438 (PyTorch Geometric \/ DGL):<\/strong> \u041e\u0431\u0443\u0447\u0435\u043d\u0438\u0435 \u044d\u043c\u0431\u0435\u0434\u0434\u0438\u043d\u0433\u043e\u0432 \u0443\u0437\u043b\u043e\u0432 \u0432 \u0433\u0440\u0430\u0444\u0430\u0445 \u043d\u0430 \u0434\u0435\u0441\u044f\u0442\u043a\u0438 \u043c\u0438\u043b\u043b\u0438\u043e\u043d\u043e\u0432 \u0432\u0435\u0440\u0448\u0438\u043d (<code>Node2Vec<\/code>, <code>HeteroData<\/code> \u0438 \u0442.\u0434.).<\/p>\n<\/li>\n<li>\n<p><strong>Knowledge Graph Embeddings :<\/strong> \u041e\u0431\u0443\u0447\u0435\u043d\u0438\u0435 \u0432 \u043d\u0435\u0435\u0432\u043a\u043b\u0438\u0434\u043e\u0432\u044b\u0445 \u0433\u0435\u043e\u043c\u0435\u0442\u0440\u0438\u044f\u0445, Complex \u043d\u0430 \u0431\u043e\u043b\u044c\u0448\u0438\u0445 \u0433\u0440\u0430\u0444\u0430\u0445 \u0437\u043d\u0430\u043d\u0438\u0439.<\/p>\n<\/li>\n<li>\n<p><strong>\u0420\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0441\u0438\u0441\u0442\u0435\u043c\u044b (RecSys):<\/strong> \u041e\u0433\u0440\u043e\u043c\u043d\u044b\u0435 \u0442\u0430\u0431\u043b\u0438\u0446\u044b \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u0438 \u0442\u043e\u0432\u0430\u0440\u043e\u0432 (Lookup Tables).<\/p>\n<\/li>\n<li>\n<p><strong>\u0418\u0441\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u0438 \u0441 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043d\u044b\u043c \u0431\u044e\u0434\u0436\u0435\u0442\u043e\u043c:<\/strong> \u0412\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u044d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u044b \u043d\u0430 \u043e\u0434\u043d\u043e\u0439 \u0432\u0438\u0434\u0435\u043e\u043a\u0430\u0440\u0442\u0435  \u0438\u043b\u0438 \u0432 \u0431\u0435\u0441\u043f\u043b\u0430\u0442\u043d\u043e\u043c Google Colab \u0431\u0435\u0437 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u0430\u0440\u0435\u043d\u0434\u043e\u0432\u0430\u0442\u044c \u0441\u0435\u0440\u0432\u0435\u0440\u044b.<\/p>\n<\/li>\n<\/ol>\n<hr\/>\n<h4>\u041e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f<\/h4>\n<ul>\n<li>\n<p><strong>SSD \u0436\u0435\u043b\u0430\u0442\u0435\u043b\u0435\u043d:<\/strong> \u0414\u043b\u044f \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0439 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0438 \u043b\u0443\u0447\u0448\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c NVMe SSD. \u041d\u0430 \u0441\u0442\u0430\u0440\u044b\u0445 \u043c\u0435\u0434\u043b\u0435\u043d\u043d\u044b\u0445 HDD \u0434\u0438\u0441\u043a\u043e\u0432\u044b\u0439 \u0432\u0432\u043e\u0434-\u0432\u044b\u0432\u043e\u0434 \u0431\u0443\u0434\u0435\u0442 \u0443\u0437\u043a\u0438\u043c \u043c\u0435\u0441\u0442\u043e\u043c.<\/p>\n<\/li>\n<li>\n<p><strong>\u0422\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f \u0440\u0430\u0437\u0440\u0435\u0436\u0435\u043d\u043d\u044b\u0445 (Sparse) \u0433\u0440\u0430\u0434\u0438\u0435\u043d\u0442\u043e\u0432:<\/strong> DSA \u0441\u043e\u0437\u0434\u0430\u043d \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u043e \u0434\u043b\u044f <code>sparse=True<\/code> \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 (\u0442\u0430\u043a\u0438\u0445 \u043a\u0430\u043a <code>torch.nn.Embedding<\/code> \u0438\u043b\u0438 <code>EmbeddingBag<\/code>). \u0414\u043b\u044f \u043f\u043b\u043e\u0442\u043d\u044b\u0445 \u0441\u0432\u0435\u0440\u0442\u043e\u0447\u043d\u044b\u0445 \u0441\u043b\u043e\u0435\u0432 \u0438\u043b\u0438 \u0442\u0440\u0430\u043d\u0441\u0444\u043e\u0440\u043c\u0435\u0440\u043e\u0432 \u0435\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043d\u0435\u0442 \u0441\u043c\u044b\u0441\u043b\u0430.<\/p>\n<\/li>\n<\/ul>\n<hr\/>\n<h4>\u0417\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435<\/h4>\n<p>\u041f\u0440\u043e\u0435\u043a\u0442 \u0440\u0430\u0441\u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u044f\u0435\u0442\u0441\u044f \u043f\u043e\u0434 \u043e\u0442\u043a\u0440\u044b\u0442\u043e\u0439 \u043b\u0438\u0446\u0435\u043d\u0437\u0438\u0435\u0439 MIT. \u0418\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u043a\u043e\u0434 \u043d\u0430 GitHub:<\/p>\n<p>\ud83d\udc49 <strong>\u0420\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 \u043d\u0430 GitHub:<\/strong> <a href=\"https:\/\/github.com\/Assistentus\/DSA\" rel=\"noopener noreferrer nofollow\">github.com\/Assistentus\/DSA<\/a><\/p>\n<p>\u0411\u0443\u0434\u0443 \u0440\u0430\u0434 \u0432\u0430\u0448\u0438\u043c \u0437\u0432\u0435\u0437\u0434\u0430\u043c \u2b50 \u043d\u0430 GitHub, \u0444\u0438\u0434\u0431\u0435\u043a\u0443 \u0432 Issues \u0438 \u043f\u0443\u043b\u043b-\u0440\u0435\u043a\u0432\u0435\u0441\u0442\u0430\u043c! \u0415\u0441\u043b\u0438 \u0443 \u0432\u0430\u0441 \u0435\u0441\u0442\u044c \u0437\u0430\u0434\u0430\u0447\u0438 \u0441 \u0431\u043e\u043b\u044c\u0448\u0438\u043c\u0438 \u0433\u0440\u0430\u0444\u0430\u043c\u0438 \u0438\u043b\u0438 \u044d\u043c\u0431\u0435\u0434\u0434\u0438\u043d\u0433\u0430\u043c\u0438 \u2014 \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0439\u0442\u0435 DSA \u0438 \u0434\u0435\u043b\u0438\u0442\u0435\u0441\u044c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0430\u043c\u0438 \u0432 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u044f\u0445.<\/p>\n<h4>\ud83e\uddea \u0411\u0435\u043d\u0447\u043c\u0430\u0440\u043a: \u0417\u0430\u043f\u0443\u0441\u043a \u043d\u0430 1 000 000 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0435\u0439 \u0432 Kaggle Notebook<\/h4>\n<p>\ud83d\udc49 <a href=\"https:\/\/www.kaggle.com\/datasets\/assistentus\/disk-sparse-adam\" rel=\"noopener noreferrer nofollow\">Kagge<\/a><\/p>\n<p>\u0417\u0430\u0434\u0430\u0447\u0430: \u043f\u0440\u043e\u0433\u043d\u0430\u0442\u044c \u043e\u0431\u0443\u0447\u0435\u043d\u0438\u0435 \u043d\u0430 <strong>1,000,000 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0435\u0439<\/strong> (\u0432\u0435\u043a\u0442\u043e\u0440\u044b \u0440\u0430\u0437\u043c\u0435\u0440\u043d\u043e\u0441\u0442\u044c\u044e 128). \u0421\u0443\u043c\u043c\u0430\u0440\u043d\u044b\u0439 \u043e\u0431\u044a\u0435\u043c \u0432\u0435\u0441\u043e\u0432 \u0438 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0439 <img decoding=\"async\" class=\"formula inline\" source=\"m\" alt=\"m\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/formulas\/6\/6f\/6f8\/6f8f57715090da2632453988d9a1501b.svg\" width=\"16\" height=\"12\" data-width=\"1.986\" data-height=\"1.025\" data-vertical-align=\"-0.025\" style=\"width: 1.986ex; height: 1.025ex; vertical-align: -0.025ex\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/getpro\/habr\/formulas\/6\/6f\/6f8\/6f8f57715090da2632453988d9a1501b.svg 780w,&#10;       https:\/\/habrastorage.org\/getpro\/habr\/formulas\/6\/6f\/6f8\/6f8f57715090da2632453988d9a1501b.svg 781w\" loading=\"lazy\" decode=\"async\"\/> \u0438 <img decoding=\"async\" class=\"formula inline\" source=\"v\" alt=\"v\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/formulas\/9\/9e\/9e3\/9e3669d19b675bd57058fd4664205d2a.svg\" width=\"12\" height=\"12\" data-width=\"1.097\" data-height=\"1.027\" data-vertical-align=\"-0.025\" style=\"width: 1.097ex; height: 1.027ex; vertical-align: -0.025ex\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/getpro\/habr\/formulas\/9\/9e\/9e3\/9e3669d19b675bd57058fd4664205d2a.svg 780w,&#10;       https:\/\/habrastorage.org\/getpro\/habr\/formulas\/9\/9e\/9e3\/9e3669d19b675bd57058fd4664205d2a.svg 781w\" loading=\"lazy\" decode=\"async\"\/> \u043d\u0430 \u0434\u0438\u0441\u043a\u0435 \u2014 <strong>~1.5 \u0413\u0411<\/strong>.<\/p>\n<pre><code class=\"python\">import osimport sysimport gcimport shutilimport timeimport subprocessimport torch# 1. \u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0430\u044f \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u0438\u0437 Kaggle Dataset \u0438\u043b\u0438 GitHubtry:    from dsa.optimizer import DiskSparseRiemannianAdamexcept ImportError:    try:        subprocess.check_call([sys.executable, \"-m\", \"pip\", \"install\", \"-q\", \"git+https:\/\/github.com\/Assistentus\/DSA.git\"])    except Exception:        !pip install -q --no-index --find-links=\/kaggle\/input\/datasets\/assistentus\/disk-sparse-adam disk-sparse-adam    from dsa.optimizer import DiskSparseRiemannianAdamdevice = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")# \u041f\u0443\u0442\u044c \u043a \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u043c\u0443 NVMe \u0434\u0438\u0441\u043a\u0443 KaggleKAGGLE_CACHE_DIR = \"\/kaggle\/working\/dsa_optimizer_cache\"if os.path.exists(KAGGLE_CACHE_DIR):    shutil.rmtree(KAGGLE_CACHE_DIR)os.makedirs(KAGGLE_CACHE_DIR, exist_ok=True)# 1,000,000 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0435\u0439 x 128 \u0438\u0437\u043c\u0435\u0440\u0435\u043d\u0438\u0439num_entities = 1_000_000embedding_dim = 128batch_size = 2048initial_embeddings = torch.randn(num_entities, embedding_dim) * 0.01# \u0424\u0438\u043a\u0441\u0438\u0440\u0443\u0435\u043c VRAM \u0434\u043e \u0441\u0442\u0430\u0440\u0442\u0430vram_baseline = torch.cuda.max_memory_allocated() \/ (1024**2) if torch.cuda.is_available() else 0optimizer = DiskSparseRiemannianAdam(    params={\"entity_emb\": initial_embeddings},    lr=0.01,    k=0.0,    disk_dir=KAGGLE_CACHE_DIR,    max_queue_size=300)print(f\"\ud83d\ude80 \u0421\u0442\u0430\u0440\u0442 \u043e\u0431\u0443\u0447\u0435\u043d\u0438\u044f {num_entities:,} \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0435\u0439 \u043d\u0430 Kaggle GPU...\")epochs = 20start_time = time.time()for epoch in range(1, epochs + 1):    batch_indices = torch.randint(0, num_entities, (batch_size,))    idx_np = batch_indices.numpy()        # \u0421\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u043c \u0442\u0435\u043a\u0443\u0449\u0438\u0435 \u0432\u0435\u0441\u0430 \u0438\u0437 mmap-\u043a\u044d\u0448\u0430 \u043d\u0430 \u0434\u0438\u0441\u043a\u0435    weights_np = optimizer.state_files[\"entity_emb\"][\"w\"][idx_np].copy()    current_weights = torch.from_numpy(weights_np).to(device).requires_grad_(True)        loss = torch.mean((current_weights) ** 2)    loss.backward()        optimizer.step(updates={\"entity_emb\": (batch_indices, current_weights.grad.cpu())})        if epoch % 5 == 0 or epoch == 1:        vram_current = torch.cuda.max_memory_allocated() \/ (1024**2) if torch.cuda.is_available() else 0        print(f\"Epoch {epoch:02d}\/{epochs} | Loss: {loss.item():.6f} | GPU VRAM Overhead: {vram_current - vram_baseline:.2f} MB\")total_time = time.time() - start_timesamples_per_sec = (epochs * batch_size) \/ total_timeprint(f\"\\n\ud83d\udcca \u041c\u0415\u0422\u0420\u0418\u041a\u0418 \u0411\u0415\u041d\u0427\u041c\u0410\u0420\u041a\u0410:\")print(f\" \ud83d\udd39 \u041f\u0440\u043e\u043f\u0443\u0441\u043a\u043d\u0430\u044f \u0441\u043f\u043e\u0441\u043e\u0431\u043d\u043e\u0441\u0442\u044c : {samples_per_sec:,.0f} \u043e\u0431\u0440\u0430\u0437\u0446\u043e\u0432 \/ \u0441\u0435\u043a\")print(f\" \ud83d\udd39 \u041f\u0440\u0438\u0440\u043e\u0441\u0442 VRAM \u043d\u0430 GPU     : 0.00 MB (\u0421\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0442\u043e\u0440\u0430 \u0432\u044b\u043d\u0435\u0441\u0435\u043d\u044b \u043d\u0430 \u0434\u0438\u0441\u043a)\")print(f\" \ud83d\udd39 \u0424\u0438\u043d\u0430\u043b\u044c\u043d\u044b\u0439 Loss          : {loss.item():.6f}\")optimizer.shutdown(timeout=2.0)del optimizergc.collect()if os.path.exists(KAGGLE_CACHE_DIR):    shutil.rmtree(KAGGLE_CACHE_DIR)<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0431\u0435\u043d\u0447\u043c\u0430\u0440\u043a\u0430 \u0432 \u043a\u043e\u043d\u0441\u043e\u043b\u0438:<\/p>\n<pre><code class=\"python\">\ud83d\ude80 \u0421\u0442\u0430\u0440\u0442 \u043e\u0431\u0443\u0447\u0435\u043d\u0438\u044f 1,000,000 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0435\u0439 \u043d\u0430 Kaggle GPU...Epoch 01\/20 | Loss: 0.000100 | GPU VRAM Overhead: 0.00 MBEpoch 05\/20 | Loss: 0.000078 | GPU VRAM Overhead: 0.00 MBEpoch 10\/20 | Loss: 0.000054 | GPU VRAM Overhead: 0.00 MBEpoch 15\/20 | Loss: 0.000039 | GPU VRAM Overhead: 0.00 MBEpoch 20\/20 | Loss: 0.000028 | GPU VRAM Overhead: 0.00 MB\ud83d\udcca \u041c\u0415\u0422\u0420\u0418\u041a\u0418 \u0411\u0415\u041d\u0427\u041c\u0410\u0420\u041a\u0410: \ud83d\udd39 \u041f\u0440\u043e\u043f\u0443\u0441\u043a\u043d\u0430\u044f \u0441\u043f\u043e\u0441\u043e\u0431\u043d\u043e\u0441\u0442\u044c : 134,212 \u043e\u0431\u0440\u0430\u0437\u0446\u043e\u0432 \/ \u0441\u0435\u043a \ud83d\udd39 \u041f\u0440\u0438\u0440\u043e\u0441\u0442 VRAM \u043d\u0430 GPU     : 0.00 MB (\u0421\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0442\u043e\u0440\u0430 \u0432\u044b\u043d\u0435\u0441\u0435\u043d\u044b \u043d\u0430 \u0434\u0438\u0441\u043a) \ud83d\udd39 \u0424\u0438\u043d\u0430\u043b\u044c\u043d\u044b\u0439 Loss          : 0.000028<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0421\u043f\u0430\u0441\u0438\u0431\u043e \u0447\u0442\u043e \u0434\u043e\u0447\u0438\u0442\u0430\u043b)<\/p>\n<\/div>\n<p>\u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/1068202\/\">https:\/\/habr.com\/ru\/articles\/1068202\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u0415\u0441\u043b\u0438 \u0432\u044b \u043e\u0431\u0443\u0447\u0430\u0435\u0442\u0435 \u0433\u0440\u0430\u0444\u043d\u044b\u0435 \u043d\u0435\u0439\u0440\u043e\u0441\u0435\u0442\u0438  \u0438\u043b\u0438 Knowledge Graph Embeddings \u043d\u0430 \u043c\u0438\u043b\u043b\u0438\u043e\u043d\u044b \u0443\u0437\u043b\u043e\u0432, \u0432\u044b \u043d\u0430\u0432\u0435\u0440\u043d\u044f\u043a\u0430 \u0441\u0442\u0430\u043b\u043a\u0438\u0432\u0430\u043b\u0438\u0441\u044c \u0441 \u0442\u0435\u043c, \u0447\u0442\u043e \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0439 torch.optim.SparseAdam \u043c\u043e\u043c\u0435\u043d\u0442\u0430\u043b\u044c\u043d\u043e \u0437\u0430\u0431\u0438\u0432\u0430\u0435\u0442 \u0432\u0441\u044e \u043e\u043f\u0435\u0440\u0430\u0442\u0438\u0432\u043d\u0443\u044e \u043f\u0430\u043c\u044f\u0442\u044c  \u0438\u043b\u0438 \u0432\u0438\u0434\u0435\u043e\u043f\u0430\u043c\u044f\u0442\u044c.\u042f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0430\u043b \u043c\u0430\u043b\u0435\u043d\u044c\u043a\u0438\u0439 \u043f\u0430\u043a\u0435\u0442 Disk Sparse Adam (DSA) \u2014 Out-of-Core \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0442\u043e\u0440 \u0434\u043b\u044f PyTorch, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u044b\u043d\u043e\u0441\u0438\u0442 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u043c\u043e\u043c\u0435\u043d\u0442\u043e\u0432 ( \u0438 ) \u043d\u0430 \u0434\u0438\u0441\u043a \u0447\u0435\u0440\u0435\u0437 mmap. \u042d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043e\u0431\u0443\u0447\u0430\u0442\u044c \u043e\u0433\u0440\u043e\u043c\u043d\u044b\u0435 \u0441\u043f\u0430\u0440\u0441-\u043c\u043e\u0434\u0435\u043b\u0438 \u043d\u0430 \u043e\u0431\u044b\u0447\u043d\u044b\u0445 \u043f\u043e\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0445 \u0432\u0438\u0434\u0435\u043e\u043a\u0430\u0440\u0442\u0430\u0445 (RTX 3090\/4090 \u0438\u043b\u0438 \u0434\u0430\u0436\u0435 \u0431\u0435\u0441\u043f\u043b\u0430\u0442\u043d\u043e\u043c Colab) \u043f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0431\u0435\u0437 \u0440\u0430\u0441\u0445\u043e\u0434\u0430 \u043f\u0430\u043c\u044f\u0442\u0438 \u043f\u043e\u0434 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0442\u043e\u0440.\u0412 \u0447\u0435\u043c \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 \u0441\u043e \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u043c SparseAdam?\u0417\u0430\u0434\u0430\u0447\u0430: \u043e\u0431\u0443\u0447\u0438\u0442\u044c \u043c\u043e\u0434\u0435\u043b\u044c \u0434\u043b\u044f Knowledge Graph \u043d\u0430 10 \u043c\u0438\u043b\u043b\u0438\u043e\u043d\u043e\u0432 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0435\u0439 \u0441 \u0440\u0430\u0437\u043c\u0435\u0440\u043d\u043e\u0441\u0442\u044c\u044e \u0432\u0435\u043a\u0442\u043e\u0440\u0430 128.\u041f\u043e\u0441\u0447\u0438\u0442\u0430\u0435\u043c \u043f\u0430\u043c\u044f\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f \u0442\u0430\u0431\u043b\u0438\u0446\u044b \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 \u0432 float32:\u0421\u0430\u043c\u0438 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b (Weight): 10,000,000 * 128 * 4 \u0431\u0430\u0439\u0442\u0430 = ~5.12 \u0413\u0411\u041a\u0430\u0437\u0430\u043b\u043e\u0441\u044c \u0431\u044b, 5 \u0413\u0411 \u043b\u0435\u0433\u043a\u043e \u0432\u043b\u0435\u0437\u0430\u044e\u0442 \u0432 \u043b\u044e\u0431\u0443\u044e \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e \u0432\u0438\u0434\u0435\u043e\u043a\u0430\u0440\u0442\u0443 \u0441 16\u201324 \u0413\u0411 VRAM \u0438\u043b\u0438 \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u0443\u044e RAM. \u041d\u043e \u043a\u0430\u043a \u0442\u043e\u043b\u044c\u043a\u043e \u043c\u044b \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u043c \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0439 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0442\u043e\u0440 torch.optim.SparseAdam, \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b:\u041f\u0435\u0440\u0432\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 (): \u0435\u0449\u0435 5.12 \u0413\u0411\u0412\u0442\u043e\u0440\u043e\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 (): \u0435\u0449\u0435 5.12 \u0413\u0411\u0418\u0442\u043e\u0433\u043e \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0442\u043e\u0440 \u00ab\u043d\u0430 \u0440\u043e\u0432\u043d\u043e\u043c \u043c\u0435\u0441\u0442\u0435\u00bb \u0437\u0430\u0431\u0438\u0440\u0430\u0435\u0442 10.24 \u0413\u0411 \u043f\u0430\u043c\u044f\u0442\u0438 \u043f\u043e\u0434 \u0438\u0441\u0442\u043e\u0440\u0438\u044e \u0433\u0440\u0430\u0434\u0438\u0435\u043d\u0442\u043e\u0432. \u0415\u0441\u043b\u0438 \u0443\u0432\u0435\u043b\u0438\u0447\u0438\u0442\u044c \u0440\u0430\u0437\u043c\u0435\u0440\u043d\u043e\u0441\u0442\u044c \u0434\u043e 256 \u0438\u043b\u0438 \u0432\u0437\u044f\u0442\u044c \u0433\u0440\u0430\u0444 \u043d\u0430 50 \u043c\u043b\u043d \u0443\u0437\u043b\u043e\u0432 \u2014 \u043f\u0430\u043c\u044f\u0442\u044c \u043c\u043e\u043c\u0435\u043d\u0442\u0430\u043b\u044c\u043d\u043e \u0437\u0430\u043a\u0430\u043d\u0447\u0438\u0432\u0430\u0435\u0442\u0441\u044f, \u0438 PyTorch \u043f\u0430\u0434\u0430\u0435\u0442 \u0441 \u043a\u043b\u0430\u0441\u0441\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u043e\u0448\u0438\u0431\u043a\u043e\u0439:CUDA out of memory. Tried to allocate X.XX GiB&#8230;\u0438\u043b\u0438 \u0441\u0438\u0441\u0442\u0435\u043c\u0430 \u00ab\u043d\u0430\u043c\u0435\u0440\u0442\u0432\u043e\u00bb \u0432\u0435\u0448\u0430\u0435\u0442 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u0443\u044e \u0441\u0438\u0441\u0442\u0435\u043c\u0443, \u0437\u0430\u043f\u043e\u043b\u043d\u044f\u044f \u0432\u0435\u0441\u044c SWAP.\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\u2502              \u041f\u0430\u043c\u044f\u0442\u044c \u043f\u0440\u0438 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u043c SparseAdam           \u2502\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\u2502 [\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b: 5.12 \u0413\u0411] + [m-state: 5.12 \u0413\u0411] + [v-state: 5.12 \u0413\u0411]   \u2502 = ~15.36 \u0413\u0411 (\u0417\u0430\u0431\u0438\u0432\u0430\u0435\u0442 VRAM\/RAM \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e)                \u2502\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\u0418\u0434\u0435\u044f: Out-of-Core \u0438 Memory Mapping (mmap)\u0412 \u0447\u0435\u043c \u043a\u043b\u044e\u0447\u0435\u0432\u0430\u044f \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0441\u0442\u044c \u0440\u0430\u0437\u0440\u0435\u0436\u0435\u043d\u043d\u043e\u0433\u043e (Sparse) \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f? \u0412 \u043a\u0430\u0436\u0434\u043e\u043c \u043c\u0438\u043d\u0438-\u0431\u0430\u0442\u0447\u0435 \u043c\u044b \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u043c \u043d\u0435 \u0432\u0441\u0435 10 \u043c\u0438\u043b\u043b\u0438\u043e\u043d\u043e\u0432 \u0443\u0437\u043b\u043e\u0432, \u0430 \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0435 \u043f\u043e\u0434\u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, 10 000 \u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0445 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0435\u0439, \u043f\u043e\u043f\u0430\u0432\u0448\u0438\u0445 \u0432 \u0442\u0435\u043a\u0443\u0449\u0438\u0439 \u0431\u0430\u0442\u0447).\u0412\u043e\u0437\u043d\u0438\u043a\u0430\u0435\u0442 \u0432\u043e\u043f\u0440\u043e\u0441: \u0437\u0430\u0447\u0435\u043c \u0434\u0435\u0440\u0436\u0430\u0442\u044c \u0432 \u0434\u043e\u0440\u043e\u0433\u043e\u0439 \u043f\u0430\u043c\u044f\u0442\u0438 GPU\/RAM \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f  \u0438  \u0434\u043b\u044f \u0432\u0441\u0435\u0445 10 \u043c\u043b\u043d \u0443\u0437\u043b\u043e\u0432 \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e, \u0435\u0441\u043b\u0438 \u043f\u0440\u044f\u043c\u043e \u0441\u0435\u0439\u0447\u0430\u0441 \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u044b \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f 10 000?\u0422\u0430\u043a \u043f\u043e\u044f\u0432\u0438\u043b\u0441\u044f Disk Sparse Adam (DSA).\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\u2502              \u041f\u0430\u043c\u044f\u0442\u044c \u043f\u0440\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 DSA                \u2502\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\u2502 VRAM \/ RAM: [\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b + \u0410\u043a\u0442\u0438\u0432\u043d\u044b\u0439 \u0431\u0430\u0442\u0447 (\u043f\u0430\u0440\u0430 \u041c\u0411)]        \u2502\u2502 DISK (mmap): [\u0418\u0441\u0442\u043e\u0440\u0438\u044f m \u0438 v \u043b\u0435\u0436\u0438\u0442 \u043d\u0430 NVMe SSD]           \u2502\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518DSA \u0432\u044b\u043d\u043e\u0441\u0438\u0442 \u043c\u0430\u0442\u0440\u0438\u0446\u044b \u043c\u043e\u043c\u0435\u043d\u0442\u043e\u0432  \u0438  \u043d\u0430 \u0434\u0438\u0441\u043a \u0432 \u0432\u0438\u0434\u0435 \u0431\u0438\u043d\u0430\u0440\u043d\u044b\u0445 \u0444\u0430\u0439\u043b\u043e\u0432 \u0438 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0435\u0442 \u0438\u0445 \u0432 \u043f\u0430\u043c\u044f\u0442\u044c \u0447\u0435\u0440\u0435\u0437 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c OS mmap (memory mapping):\u041d\u0430 \u0448\u0430\u0433\u0435 optimizer.step() DSA \u0441\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u0442 \u0441 \u0434\u0438\u0441\u043a\u0430 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u043c\u043e\u043c\u0435\u043d\u0442\u043e\u0432 \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f \u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0445 \u0438\u043d\u0434\u0435\u043a\u0441\u043e\u0432 \u0442\u0435\u043a\u0443\u0449\u0435\u0433\u043e \u0431\u0430\u0442\u0447\u0430.\u041f\u0440\u043e\u0432\u043e\u0434\u0438\u0442 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u043f\u043e \u0444\u043e\u0440\u043c\u0443\u043b\u0435 Adam.\u0417\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044b\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u043e\u0431\u0440\u0430\u0442\u043d\u043e \u043d\u0430 \u0434\u0438\u0441\u043a.\u0420\u0430\u0441\u0445\u043e\u0434 \u043e\u043f\u0435\u0440\u0430\u0442\u0438\u0432\u043d\u043e\u0439\/\u0432\u0438\u0434\u0435\u043e\u043f\u0430\u043c\u044f\u0442\u0438 \u043f\u043e\u0434 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0442\u043e\u0440\u0430 \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f \u043f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043d\u0443\u043b\u0435\u0432\u044b\u043c.\u041a\u0430\u043a \u044d\u0442\u043e \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0432 \u043a\u043e\u0434\u0435\u041e\u0434\u043d\u0430 \u0438\u0437 \u0433\u043b\u0430\u0432\u043d\u044b\u0445 \u0437\u0430\u0434\u0430\u0447 \u043f\u0440\u0438 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435 DSA \u2014 \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0435\u0433\u043e Drop-in \u0437\u0430\u043c\u0435\u043d\u043e\u0439 \u0434\u043b\u044f \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0445 \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d\u043e\u0432 PyTorch. \u0412\u0430\u043c \u043d\u0435 \u043d\u0443\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0443 \u043c\u043e\u0434\u0435\u043b\u0438 \u0438\u043b\u0438 \u0434\u0430\u0442\u0430\u043b\u043e\u0430\u0434\u0435\u0440\u044b.\u0411\u044b\u043b\u043e (\u0421\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0439 PyTorch):import torchembedding = torch.nn.EmbeddingBag(10_000_000, 128, sparse=True)optimizer = torch.optim.SparseAdam(embedding.parameters(), lr=0.001)for batch_idx in dataloader:    optimizer.zero_grad()    out = embedding(batch_idx)    loss = compute_loss(out)    loss.backward()    optimizer.step()\u0421\u0442\u0430\u043b\u043e (\u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c DSA):import torchfrom dsa.optimizer import DiskSparseRiemannianAdam# \u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u043c \u044d\u043c\u0431\u0435\u0434\u0434\u0438\u043d\u0433\u0438embedding = torch.nn.Embedding(10_000_000, 128, sparse=True)# \u0423\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c \u043f\u0430\u043f\u043a\u0443 \u043d\u0430 \u0434\u0438\u0441\u043a\u0435 \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0439 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0442\u043e\u0440\u0430optimizer = DiskSparseRiemannianAdam(    params={&#171;emb&#187;: embedding.weight},     lr=0.001,     k=0.0, # 0.0 \u2014 \u0415\u0432\u043a\u043b\u0438\u0434\u043e\u0432\u043e \u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0441\u0442\u0432\u043e, 1.0 \u2014 \u0428\u0430\u0440 \u041f\u0443\u0430\u043d\u043a\u0430\u0440\u0435 (\u0433\u0438\u043f\u0435\u0440\u0431\u043e\u043b\u0438\u0447\u0435\u0441\u043a\u043e\u0435)    disk_dir=&#187;.\/opt_cache&#187;)# \u0412 \u0446\u0438\u043a\u043b\u0435 \u043e\u0431\u0443\u0447\u0435\u043d\u0438\u044f \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u043c \u0433\u0440\u0430\u0434\u0438\u0435\u043d\u0442\u044bfor batch_indices in dataloader:    # \u0414\u043e\u0441\u0442\u0430\u0435\u043c \u0432\u0435\u0441\u0430 \u0431\u0430\u0442\u0447\u0430 \u0441 \u0434\u0438\u0441\u043a\u0430    idx_np = batch_indices.numpy()    weights_np = optimizer.state_files[&#171;emb&#187;][&#171;w&#187;][idx_np].copy()    current_weights = torch.from_numpy(weights_np).requires_grad_(True)        loss = compute_loss(current_weights)    loss.backward()        # \u041f\u0435\u0440\u0435\u0434\u0430\u0435\u043c \u0438\u043d\u0434\u0435\u043a\u0441\u044b \u0438 \u0433\u0440\u0430\u0434\u0438\u0435\u043d\u0442\u044b \u0432 DSA    optimizer.step(updates={&#171;emb&#187;: (batch_indices, current_weights.grad)})# \u0424\u0438\u043d\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u043c \u0444\u043e\u043d\u043e\u0432\u044b\u0439 \u043f\u043e\u0442\u043e\u043a \u0437\u0430\u043f\u0438\u0441\u0438optimizer.shutdown()\u0421\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u0435 \u0438 \u041f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c1. \u041f\u043e\u0442\u0440\u0435\u0431\u043b\u0435\u043d\u0438\u0435 \u043f\u0430\u043c\u044f\u0442\u0438 (RAM \/ VRAM)\u0421 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c DSA \u0440\u0430\u0441\u0445\u043e\u0434 \u043f\u0430\u043c\u044f\u0442\u0438 \u043f\u043e\u0434 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0442\u043e\u0440\u0430 \u0441\u043d\u0438\u0436\u0430\u0435\u0442\u0441\u044f \u043e\u0442 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u0433\u0438\u0433\u0430\u0431\u0430\u0439\u0442 \u0434\u043e\u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u043c\u0435\u0433\u0430\u0431\u0430\u0439\u0442 (\u0437\u0430\u0432\u0438\u0441\u0438\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0442 \u0440\u0430\u0437\u043c\u0435\u0440\u0430 \u043c\u0438\u043d\u0438-\u0431\u0430\u0442\u0447\u0430). \u042d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043e\u0431\u0443\u0447\u0430\u0442\u044c \u043c\u043e\u0434\u0435\u043b\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0440\u0430\u043d\u044c\u0448\u0435 \u0432 \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u0435 \u043d\u0435 \u043f\u043e\u043c\u0435\u0449\u0430\u043b\u0438\u0441\u044c \u043d\u0430 \u0440\u0430\u0431\u043e\u0447\u0435\u0439 \u0441\u0442\u0430\u043d\u0446\u0438\u0438.2. \u0421\u043a\u043e\u0440\u043e\u0441\u0442\u044c I\/O\u041a\u043e\u043d\u0435\u0447\u043d\u043e \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u043e\u0431\u0443\u0447\u0435\u043d\u0438\u044f \u043d\u0435 \u0441\u0440\u0430\u0432\u043d\u0438\u0442\u0441\u044f \u0441 \u043e\u0431\u0443\u0447\u0435\u043d\u0438\u0435\u043c \u043d\u0430 GPU \u043d\u043e  \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0439 NVMe SSD \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0432\u0430\u0435\u0442 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u043e\u0433\u043e \u0447\u0442\u0435\u043d\u0438\u044f\/\u0437\u0430\u043f\u0438\u0441\u0438 \u0432 \u0434\u0435\u0441\u044f\u0442\u043a\u0438 \u0442\u044b\u0441\u044f\u0447 IOPS(\u043d\u0435 \u0438\u0437\u043c\u0435\u0440\u044f\u043b), \u0430 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u0430\u044f \u0441\u0438\u0441\u0442\u0435\u043c\u0430 \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e \u043a\u044d\u0448\u0438\u0440\u0443\u0435\u0442 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u0447\u0435\u0440\u0435\u0437 Page Cache, \u043d\u0430\u043a\u043b\u0430\u0434\u043d\u044b\u0435 \u0440\u0430\u0441\u0445\u043e\u0434\u044b \u043d\u0430 \u0434\u0438\u0441\u043a \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u044b \u0438 \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u043f\u0435\u0440\u0435\u043a\u0440\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u044d\u043a\u043e\u043d\u043e\u043c\u0438\u0435\u0439 \u043f\u0430\u043c\u044f\u0442\u0438.\u0413\u0434\u0435 \u044d\u0442\u043e \u043f\u0440\u0438\u0433\u043e\u0434\u0438\u0442\u0441\u044f?GNN \u0438 \u0433\u0440\u0430\u0444\u043d\u044b\u0435 \u043d\u0435\u0439\u0440\u043e\u0441\u0435\u0442\u0438 (PyTorch Geometric \/ DGL): \u041e\u0431\u0443\u0447\u0435\u043d\u0438\u0435 \u044d\u043c\u0431\u0435\u0434\u0434\u0438\u043d\u0433\u043e\u0432 \u0443\u0437\u043b\u043e\u0432 \u0432 \u0433\u0440\u0430\u0444\u0430\u0445 \u043d\u0430 \u0434\u0435\u0441\u044f\u0442\u043a\u0438 \u043c\u0438\u043b\u043b\u0438\u043e\u043d\u043e\u0432 \u0432\u0435\u0440\u0448\u0438\u043d (Node2Vec, HeteroData \u0438 \u0442.\u0434.).Knowledge Graph Embeddings : \u041e\u0431\u0443\u0447\u0435\u043d\u0438\u0435 \u0432 \u043d\u0435\u0435\u0432\u043a\u043b\u0438\u0434\u043e\u0432\u044b\u0445 \u0433\u0435\u043e\u043c\u0435\u0442\u0440\u0438\u044f\u0445, Complex \u043d\u0430 \u0431\u043e\u043b\u044c\u0448\u0438\u0445 \u0433\u0440\u0430\u0444\u0430\u0445 \u0437\u043d\u0430\u043d\u0438\u0439.\u0420\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0441\u0438\u0441\u0442\u0435\u043c\u044b (RecSys): \u041e\u0433\u0440\u043e\u043c\u043d\u044b\u0435 \u0442\u0430\u0431\u043b\u0438\u0446\u044b \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u0438 \u0442\u043e\u0432\u0430\u0440\u043e\u0432 (Lookup Tables).\u0418\u0441\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u0438 \u0441 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043d\u044b\u043c \u0431\u044e\u0434\u0436\u0435\u0442\u043e\u043c: \u0412\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u044d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u044b \u043d\u0430 \u043e\u0434\u043d\u043e\u0439 \u0432\u0438\u0434\u0435\u043e\u043a\u0430\u0440\u0442\u0435  \u0438\u043b\u0438 \u0432 \u0431\u0435\u0441\u043f\u043b\u0430\u0442\u043d\u043e\u043c Google Colab \u0431\u0435\u0437 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u0430\u0440\u0435\u043d\u0434\u043e\u0432\u0430\u0442\u044c \u0441\u0435\u0440\u0432\u0435\u0440\u044b.\u041e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044fSSD \u0436\u0435\u043b\u0430\u0442\u0435\u043b\u0435\u043d: \u0414\u043b\u044f \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0439 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0438 \u043b\u0443\u0447\u0448\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c NVMe SSD. \u041d\u0430 \u0441\u0442\u0430\u0440\u044b\u0445 \u043c\u0435\u0434\u043b\u0435\u043d\u043d\u044b\u0445 HDD \u0434\u0438\u0441\u043a\u043e\u0432\u044b\u0439 \u0432\u0432\u043e\u0434-\u0432\u044b\u0432\u043e\u0434 \u0431\u0443\u0434\u0435\u0442 \u0443\u0437\u043a\u0438\u043c \u043c\u0435\u0441\u0442\u043e\u043c.\u0422\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f \u0440\u0430\u0437\u0440\u0435\u0436\u0435\u043d\u043d\u044b\u0445 (Sparse) \u0433\u0440\u0430\u0434\u0438\u0435\u043d\u0442\u043e\u0432: DSA \u0441\u043e\u0437\u0434\u0430\u043d \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u043e \u0434\u043b\u044f sparse=True \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 (\u0442\u0430\u043a\u0438\u0445 \u043a\u0430\u043a torch.nn.Embedding \u0438\u043b\u0438 EmbeddingBag). \u0414\u043b\u044f \u043f\u043b\u043e\u0442\u043d\u044b\u0445 \u0441\u0432\u0435\u0440\u0442\u043e\u0447\u043d\u044b\u0445 \u0441\u043b\u043e\u0435\u0432 \u0438\u043b\u0438 \u0442\u0440\u0430\u043d\u0441\u0444\u043e\u0440\u043c\u0435\u0440\u043e\u0432 \u0435\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043d\u0435\u0442 \u0441\u043c\u044b\u0441\u043b\u0430.\u0417\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435\u041f\u0440\u043e\u0435\u043a\u0442 \u0440\u0430\u0441\u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u044f\u0435\u0442\u0441\u044f \u043f\u043e\u0434 \u043e\u0442\u043a\u0440\u044b\u0442\u043e\u0439 \u043b\u0438\u0446\u0435\u043d\u0437\u0438\u0435\u0439 MIT. \u0418\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u043a\u043e\u0434 \u043d\u0430 GitHub:\ud83d\udc49 \u0420\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 \u043d\u0430 GitHub: github.com\/Assistentus\/DSA\u0411\u0443\u0434\u0443 \u0440\u0430\u0434 \u0432\u0430\u0448\u0438\u043c \u0437\u0432\u0435\u0437\u0434\u0430\u043c \u2b50 \u043d\u0430 GitHub, \u0444\u0438\u0434\u0431\u0435\u043a\u0443 \u0432 Issues \u0438 \u043f\u0443\u043b\u043b-\u0440\u0435\u043a\u0432\u0435\u0441\u0442\u0430\u043c! \u0415\u0441\u043b\u0438 \u0443 \u0432\u0430\u0441 \u0435\u0441\u0442\u044c \u0437\u0430\u0434\u0430\u0447\u0438 \u0441 \u0431\u043e\u043b\u044c\u0448\u0438\u043c\u0438 \u0433\u0440\u0430\u0444\u0430\u043c\u0438 \u0438\u043b\u0438 \u044d\u043c\u0431\u0435\u0434\u0434\u0438\u043d\u0433\u0430\u043c\u0438 \u2014 \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0439\u0442\u0435 DSA \u0438 \u0434\u0435\u043b\u0438\u0442\u0435\u0441\u044c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0430\u043c\u0438 \u0432 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u044f\u0445.\ud83e\uddea \u0411\u0435\u043d\u0447\u043c\u0430\u0440\u043a: \u0417\u0430\u043f\u0443\u0441\u043a \u043d\u0430 1 000 000 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0435\u0439 \u0432 Kaggle Notebook\ud83d\udc49 Kagge\u0417\u0430\u0434\u0430\u0447\u0430: \u043f\u0440\u043e\u0433\u043d\u0430\u0442\u044c \u043e\u0431\u0443\u0447\u0435\u043d\u0438\u0435 \u043d\u0430 1,000,000 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0435\u0439 (\u0432\u0435\u043a\u0442\u043e\u0440\u044b \u0440\u0430\u0437\u043c\u0435\u0440\u043d\u043e\u0441\u0442\u044c\u044e 128). \u0421\u0443\u043c\u043c\u0430\u0440\u043d\u044b\u0439 \u043e\u0431\u044a\u0435\u043c \u0432\u0435\u0441\u043e\u0432 \u0438 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0439  \u0438  \u043d\u0430 \u0434\u0438\u0441\u043a\u0435 \u2014 ~1.5 \u0413\u0411.import osimport sysimport gcimport shutilimport timeimport subprocessimport torch# 1. \u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0430\u044f \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u0438\u0437 Kaggle Dataset \u0438\u043b\u0438 GitHubtry:    from dsa.optimizer import DiskSparseRiemannianAdamexcept ImportError:    try:        subprocess.check_call([sys.executable, &#171;-m&#187;, &#171;pip&#187;, &#171;install&#187;, &#171;-q&#187;, &#171;git+https:\/\/github.com\/Assistentus\/DSA.git&#187;])    except Exception:        !pip install -q &#8212;no-index &#8212;find-links=\/kaggle\/input\/datasets\/assistentus\/disk-sparse-adam disk-sparse-adam    from dsa.optimizer import DiskSparseRiemannianAdamdevice = torch.device(&#171;cuda&#187; if torch.cuda.is_available() else &#171;cpu&#187;)# \u041f\u0443\u0442\u044c \u043a \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u043c\u0443 NVMe \u0434\u0438\u0441\u043a\u0443 KaggleKAGGLE_CACHE_DIR = &#171;\/kaggle\/working\/dsa_optimizer_cache&#187;if os.path.exists(KAGGLE_CACHE_DIR):    shutil.rmtree(KAGGLE_CACHE_DIR)os.makedirs(KAGGLE_CACHE_DIR, exist_ok=True)# 1,000,000 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0435\u0439 x 128 \u0438\u0437\u043c\u0435\u0440\u0435\u043d\u0438\u0439num_entities = 1_000_000embedding_dim = 128batch_size = 2048initial_embeddings = torch.randn(num_entities, embedding_dim) * 0.01# \u0424\u0438\u043a\u0441\u0438\u0440\u0443\u0435\u043c VRAM \u0434\u043e \u0441\u0442\u0430\u0440\u0442\u0430vram_baseline = torch.cuda.max_memory_allocated() \/ (1024**2) if torch.cuda.is_available() else 0optimizer = DiskSparseRiemannianAdam(    params={&#171;entity_emb&#187;: initial_embeddings},    lr=0.01,    k=0.0,    disk_dir=KAGGLE_CACHE_DIR,    max_queue_size=300)print(f&#187;\ud83d\ude80 \u0421\u0442\u0430\u0440\u0442 \u043e\u0431\u0443\u0447\u0435\u043d\u0438\u044f {num_entities:,} \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0435\u0439 \u043d\u0430 Kaggle GPU&#8230;&#187;)epochs = 20start_time = time.time()for epoch in range(1, epochs + 1):    batch_indices = torch.randint(0, num_entities, (batch_size,))    idx_np = batch_indices.numpy()        # \u0421\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u043c \u0442\u0435\u043a\u0443\u0449\u0438\u0435 \u0432\u0435\u0441\u0430 \u0438\u0437 mmap-\u043a\u044d\u0448\u0430 \u043d\u0430 \u0434\u0438\u0441\u043a\u0435    weights_np = optimizer.state_files[&#171;entity_emb&#187;][&#171;w&#187;][idx_np].copy()    current_weights = torch.from_numpy(weights_np).to(device).requires_grad_(True)        loss = torch.mean((current_weights) ** 2)    loss.backward()        optimizer.step(updates={&#171;entity_emb&#187;: (batch_indices, current_weights.grad.cpu())})        if epoch % 5 == 0 or epoch == 1:        vram_current = torch.cuda.max_memory_allocated() \/ (1024**2) if torch.cuda.is_available() else 0        print(f&#187;Epoch {epoch:02d}\/{epochs} | Loss: {loss.item():.6f} | GPU VRAM Overhead: {vram_current &#8212; vram_baseline:.2f} MB&#187;)total_time = time.time() &#8212; start_timesamples_per_sec = (epochs * batch_size) \/ total_timeprint(f&#187;\\n\ud83d\udcca \u041c\u0415\u0422\u0420\u0418\u041a\u0418 \u0411\u0415\u041d\u0427\u041c\u0410\u0420\u041a\u0410:&#187;)print(f&#187; \ud83d\udd39 \u041f\u0440\u043e\u043f\u0443\u0441\u043a\u043d\u0430\u044f \u0441\u043f\u043e\u0441\u043e\u0431\u043d\u043e\u0441\u0442\u044c : {samples_per_sec:,.0f} \u043e\u0431\u0440\u0430\u0437\u0446\u043e\u0432 \/ \u0441\u0435\u043a&#187;)print(f&#187; \ud83d\udd39 \u041f\u0440\u0438\u0440\u043e\u0441\u0442 VRAM \u043d\u0430 GPU     : 0.00 MB (\u0421\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0442\u043e\u0440\u0430 \u0432\u044b\u043d\u0435\u0441\u0435\u043d\u044b \u043d\u0430 \u0434\u0438\u0441\u043a)&#187;)print(f&#187; \ud83d\udd39 \u0424\u0438\u043d\u0430\u043b\u044c\u043d\u044b\u0439 Loss          : {loss.item():.6f}&#187;)optimizer.shutdown(timeout=2.0)del optimizergc.collect()if os.path.exists(KAGGLE_CACHE_DIR):    shutil.rmtree(KAGGLE_CACHE_DIR)\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0431\u0435\u043d\u0447\u043c\u0430\u0440\u043a\u0430 \u0432 \u043a\u043e\u043d\u0441\u043e\u043b\u0438:\ud83d\ude80 \u0421\u0442\u0430\u0440\u0442 \u043e\u0431\u0443\u0447\u0435\u043d\u0438\u044f 1,000,000 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0435\u0439 \u043d\u0430 Kaggle GPU&#8230;Epoch 01\/20 | Loss: 0.000100 | GPU VRAM Overhead: 0.00 MBEpoch 05\/20 | Loss: 0.000078 | GPU VRAM Overhead: 0.00 MBEpoch 10\/20 | Loss: 0.000054 | GPU VRAM Overhead: 0.00 MBEpoch 15\/20 | Loss: 0.000039 | GPU VRAM Overhead: 0.00 MBEpoch 20\/20 | Loss: 0.000028 | GPU VRAM Overhead: 0.00 MB\ud83d\udcca \u041c\u0415\u0422\u0420\u0418\u041a\u0418 \u0411\u0415\u041d\u0427\u041c\u0410\u0420\u041a\u0410: \ud83d\udd39 \u041f\u0440\u043e\u043f\u0443\u0441\u043a\u043d\u0430\u044f \u0441\u043f\u043e\u0441\u043e\u0431\u043d\u043e\u0441\u0442\u044c : 134,212 \u043e\u0431\u0440\u0430\u0437\u0446\u043e\u0432 \/ \u0441\u0435\u043a \ud83d\udd39 \u041f\u0440\u0438\u0440\u043e\u0441\u0442 VRAM \u043d\u0430 GPU     : 0.00 MB (\u0421\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0442\u043e\u0440\u0430 \u0432\u044b\u043d\u0435\u0441\u0435\u043d\u044b \u043d\u0430 \u0434\u0438\u0441\u043a) \ud83d\udd39 \u0424\u0438\u043d\u0430\u043b\u044c\u043d\u044b\u0439 Loss          : 0.000028\u0421\u043f\u0430\u0441\u0438\u0431\u043e \u0447\u0442\u043e \u0434\u043e\u0447\u0438\u0442\u0430\u043b)\u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 https:\/\/habr.com\/ru\/articles\/1068202\/<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-490250","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/490250","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=490250"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/490250\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=490250"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=490250"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=490250"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}