{"id":481959,"date":"2026-06-01T15:08:39","date_gmt":"2026-06-01T15:08:39","guid":{"rendered":"https:\/\/savepearlharbor.com\/?p=481959"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=481959","title":{"rendered":"200 000 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 \u0437\u0430 2 \u043c\u0441: \u043a\u0430\u043a \u0432\u044b\u0431\u0438\u0440\u0430\u0442\u044c \u0442\u043e\u043f-K \u0431\u0435\u0437 \u043f\u043e\u043b\u043d\u043e\u0439 \u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0438"},"content":{"rendered":"<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u0412 real-time \u0438\u0433\u0440\u0430\u0445 \u0438 \u0441\u0435\u0440\u0432\u0435\u0440\u0430\u0445 \u0447\u0430\u0441\u0442\u043e \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u0435\u0442 \u0437\u0430\u0434\u0430\u0447\u0430: \u0438\u0437 N \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 \u043d\u0443\u0436\u043d\u043e \u0432\u044b\u0431\u0440\u0430\u0442\u044c K \u043b\u0443\u0447\u0448\u0438\u0445, \u0447\u0442\u043e\u0431\u044b \u043e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u0438\u0445 \u0432 \u044d\u0442\u043e\u043c \u043a\u0430\u0434\u0440\u0435.<\/p>\n<ul>\n<li>\n<p>AI \u0434\u043b\u044f NPC: \u0438\u0437 50 000 \u0432\u0440\u0430\u0433\u043e\u0432 \u043e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e 1000 \u0441\u0430\u043c\u044b\u0445 \u0432\u0430\u0436\u043d\u044b\u0445.<\/p>\n<\/li>\n<li>\n<p>\u0410\u043d\u0438\u043c\u0430\u0446\u0438\u0438: \u0438\u0437 10 000 \u043f\u0435\u0440\u0441\u043e\u043d\u0430\u0436\u0435\u0439 \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u0434\u0435\u0442\u0430\u043b\u044c\u043d\u044b\u0435 \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u0438 \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f 200 \u0431\u043b\u0438\u0436\u0430\u0439\u0448\u0438\u0445 \u043a \u043a\u0430\u043c\u0435\u0440\u0435.<\/p>\n<\/li>\n<li>\n<p>VFX: \u0438\u0437 5000 \u0447\u0430\u0441\u0442\u0438\u0446 \u043e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u0442\u0435, \u0447\u0442\u043e \u0432 \u043f\u043e\u043b\u0435 \u0437\u0440\u0435\u043d\u0438\u044f.<\/p>\n<\/li>\n<li>\n<p>\u0421\u0435\u0442\u043a\u0430 LOD: \u0438\u0437 100 000 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 \u0432\u044b\u0431\u0440\u0430\u0442\u044c 5000 \u0434\u043b\u044f \u0432\u044b\u0441\u043e\u043a\u043e\u0433\u043e \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0430.<\/p>\n<\/li>\n<\/ul>\n<p>\u0422\u0438\u043f\u0438\u0447\u043d\u044b\u0439 \u043f\u043e\u0434\u0445\u043e\u0434 \u2014 \u043f\u043e\u0441\u0447\u0438\u0442\u0430\u0442\u044c \u043e\u0446\u0435\u043d\u043a\u0443 \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043e\u0431\u044a\u0435\u043a\u0442\u0430, \u0437\u0430\u0442\u0435\u043c \u043e\u0442\u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432\u0435\u0441\u044c \u043c\u0430\u0441\u0441\u0438\u0432 \u0438 \u0432\u0437\u044f\u0442\u044c \u043f\u0435\u0440\u0432\u044b\u0435 K \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432.<\/p>\n<pre><code class=\"cs\">\/\/ \u041d\u0430\u0438\u0432\u043d\u044b\u0439 \u043f\u043e\u0434\u0445\u043e\u0434: \u043f\u043e\u043b\u043d\u0430\u044f \u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0430float[] scores = new float[N];for (int i = 0; i &lt; N; i++)    scores[i] = Dot(features[i], weights);Array.Sort(scores, ids); \/\/ O(N log N)\/\/ \u0411\u0435\u0440\u0451\u043c \u043f\u0435\u0440\u0432\u044b\u0435 K<\/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>\u041f\u0440\u043e\u0431\u043b\u0435\u043c\u0430: \u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0430 200 000 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432 \u0437\u0430\u043d\u0438\u043c\u0430\u0435\u0442 <strong>~16 \u043c\u0441<\/strong>. \u042d\u0442\u043e \u0432\u0435\u0441\u044c \u0431\u044e\u0434\u0436\u0435\u0442 \u043a\u0430\u0434\u0440\u0430 \u043f\u0440\u0438 60 FPS. \u0410 \u0432\u0435\u0434\u044c \u0435\u0449\u0451 \u043d\u0443\u0436\u043d\u043e \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u0442\u044c, \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u0444\u0438\u0437\u0438\u043a\u0443, \u0442\u0438\u043a\u0430\u0442\u044c AI.<\/p>\n<p><strong>\u041f\u043e\u0447\u0435\u043c\u0443 \u043f\u043e\u043b\u043d\u0430\u044f \u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0430 \u2014 \u044d\u0442\u043e \u043f\u0435\u0440\u0435\u0431\u043e\u0440<\/strong><\/p>\n<p>\u0421\u043b\u043e\u0436\u043d\u043e\u0441\u0442\u044c O(N log N). \u0414\u043b\u044f N = 200 000 \u044d\u0442\u043e \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e 200 000 \u00d7 18 = 3.6 \u043c\u043b\u043d \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u0439. \u041f\u043b\u044e\u0441 \u0430\u043b\u043b\u043e\u043a\u0430\u0446\u0438\u0438 \u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u043c\u0430\u0441\u0441\u0438\u0432\u043e\u0432. \u041f\u043b\u044e\u0441 GC-\u043f\u0430\u0443\u0437\u044b.<\/p>\n<p>\u0410 \u0432\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0432\u0441\u0435\u0433\u043e K = 2000 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432. \u0412\u044b \u0432\u044b\u0431\u0440\u0430\u0441\u044b\u0432\u0430\u0435\u0442\u0435 198 000 \u043e\u0442c\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432. \u042d\u0442\u043e 99% \u043f\u043e\u0442\u0440\u0430\u0447\u0435\u043d\u043d\u043e\u0439 \u0440\u0430\u0431\u043e\u0442\u044b \u0432\u043f\u0443\u0441\u0442\u0443\u044e.<\/p>\n<p><strong>\u0414\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u0430\u044f \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430: \u0433\u0440\u0443\u043f\u043f\u043e\u0432\u044b\u0435 \u043a\u0432\u043e\u0442\u044b<\/strong><\/p>\n<p>\u0427\u0430\u0441\u0442\u043e \u043d\u0443\u0436\u043d\u043e \u043d\u0435 \u043f\u0440\u043e\u0441\u0442\u043e \u0442\u043e\u043f-K, \u0430 \u0441\u043f\u0440\u0430\u0432\u0435\u0434\u043b\u0438\u0432\u043e\u0435 \u0440\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u043c\u0435\u0436\u0434\u0443 \u0433\u0440\u0443\u043f\u043f\u0430\u043c\u0438:<\/p>\n<ul>\n<li>\n<p>\u0410\u043d\u0438\u043c\u0430\u0446\u0438\u0438: \u043d\u0435 \u0431\u043e\u043b\u0435\u0435 200 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432<\/p>\n<\/li>\n<li>\n<p>AI: \u043d\u0435 \u0431\u043e\u043b\u0435\u0435 500 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432<\/p>\n<\/li>\n<li>\n<p>VFX: \u043d\u0435 \u0431\u043e\u043b\u0435\u0435 300 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432<\/p>\n<\/li>\n<li>\n<p>\u0424\u0438\u0437\u0438\u043a\u0430: \u043d\u0435 \u0431\u043e\u043b\u0435\u0435 200 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432<\/p>\n<\/li>\n<\/ul>\n<p>\u0421\u0443\u043c\u043c\u0430 \u043a\u0432\u043e\u0442 = K = 1200. \u041d\u043e \u0435\u0441\u043b\u0438 \u043e\u0442\u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043e\u0431\u0449\u0438\u0439 \u0441\u043f\u0438\u0441\u043e\u043a, \u043e\u0434\u043d\u0430 \u0433\u0440\u0443\u043f\u043f\u0430 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0432\u0440\u0430\u0433\u0438) \u043c\u043e\u0436\u0435\u0442 \u0437\u0430\u043d\u044f\u0442\u044c \u0432\u0441\u0435 \u0442\u043e\u043f-1200 \u043c\u0435\u0441\u0442, \u0430 \u0434\u0440\u0443\u0433\u0438\u0435 \u0433\u0440\u0443\u043f\u043f\u044b (\u0441\u043e\u044e\u0437\u043d\u0438\u043a\u0438, \u043d\u0435\u0439\u0442\u0440\u0430\u043b\u044b) \u043d\u0435 \u043f\u043e\u043b\u0443\u0447\u0430\u0442 \u043d\u0438\u0447\u0435\u0433\u043e.<\/p>\n<p>\u041f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435: \u043e\u0442\u043e\u0431\u0440\u0430\u0442\u044c \u0442\u043e\u043f-K \u0441 \u0443\u0447\u0451\u0442\u043e\u043c \u043a\u0432\u043e\u0442 \u043d\u0430 \u0433\u0440\u0443\u043f\u043f\u0443. \u041d\u043e \u043a\u0430\u043a \u044d\u0442\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0431\u0435\u0437 \u043c\u043d\u043e\u0433\u043e\u043a\u0440\u0430\u0442\u043d\u043e\u0439 \u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0438?<\/p>\n<h3>\u0420\u0435\u0448\u0435\u043d\u0438\u0435: SIMD + \u0441\u0435\u043b\u0435\u043a\u0446\u0438\u044f \u0431\u0435\u0437 \u043f\u043e\u043b\u043d\u043e\u0439 \u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0438<\/h3>\n<p><strong>GameBudget.Net<\/strong> \u2014 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0434\u043b\u044f .NET 8.0+, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0440\u0435\u0448\u0430\u0435\u0442 \u043e\u0431\u0435 \u0437\u0430\u0434\u0430\u0447\u0438:<\/p>\n<ul>\n<li>\n<p>\u0422\u043e\u043f-K \u0447\u0435\u0440\u0435\u0437 heap-\u0441\u0435\u043b\u0435\u043a\u0446\u0438\u044e: O(N log K) \u0432\u043c\u0435\u0441\u0442\u043e O(N log N)<\/p>\n<\/li>\n<li>\n<p>\u0413\u0440\u0443\u043f\u043f\u043e\u0432\u044b\u0435 \u043a\u0432\u043e\u0442\u044b \u0447\u0435\u0440\u0435\u0437 per-group heap: O(N log q\u1d4d) (\u0433\u0434\u0435 q\u1d4d \u2014 \u043a\u0432\u043e\u0442\u0430 \u0433\u0440\u0443\u043f\u043f\u044b)<\/p>\n<\/li>\n<li>\n<p>SIMD-\u0443\u043c\u043d\u043e\u0436\u0435\u043d\u0438\u0435 \u043c\u0430\u0442\u0440\u0438\u0446 \u0434\u043b\u044f \u0441\u043a\u043e\u0440\u0438\u043d\u0433\u0430 \u0447\u0435\u0440\u0435\u0437 SlidingRank.FastOps<\/p>\n<\/li>\n<\/ul>\n<pre><code class=\"cs\">dotnet add package GameBudget.Net --version 1.0.0<\/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><strong>\u041a\u043b\u044e\u0447\u0435\u0432\u044b\u0435 \u0438\u0434\u0435\u0438<\/strong><\/p>\n<ol>\n<li>\n<p><strong>Heap-\u0441\u0435\u043b\u0435\u043a\u0446\u0438\u044f (\u0431\u0435\u0437 \u043f\u043e\u043b\u043d\u043e\u0439 \u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0438)<\/strong><\/p>\n<ul>\n<li>\n<p>\u041f\u0440\u043e\u0445\u043e\u0434\u0438\u043c \u043f\u043e \u0432\u0441\u0435\u043c N \u043e\u0431\u044a\u0435\u043a\u0442\u0430\u043c.<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u043c min-heap \u0440\u0430\u0437\u043c\u0435\u0440\u043e\u043c K.<\/p>\n<\/li>\n<li>\n<p>\u0415\u0441\u043b\u0438 \u043d\u043e\u0432\u044b\u0439 \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u043b\u0443\u0447\u0448\u0435 \u0445\u0443\u0434\u0448\u0435\u0433\u043e \u0432 \u043a\u0443\u0447\u0435 \u2014 \u0437\u0430\u043c\u0435\u043d\u044f\u0435\u043c.<\/p>\n<\/li>\n<li>\n<p>\u0412 \u043a\u043e\u043d\u0446\u0435 heap \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0442\u043e\u043f-K, \u0438\u0437\u0432\u043b\u0435\u043a\u0430\u0435\u043c \u0432 \u043e\u0442\u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u043c \u043f\u043e\u0440\u044f\u0434\u043a\u0435.<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<li>\n<p><strong>Per-group \u0441\u0435\u043b\u0435\u043a\u0446\u0438\u044f \u0441 \u043a\u0432\u043e\u0442\u0430\u043c\u0438<\/strong><\/p>\n<ul>\n<li>\n<p>\u0414\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0439 \u0433\u0440\u0443\u043f\u043f\u044b \u0441\u0432\u043e\u0439 min-heap \u0440\u0430\u0437\u043c\u0435\u0440\u043e\u043c \u0441 \u043a\u0432\u043e\u0442\u0443 \u0433\u0440\u0443\u043f\u043f\u044b.<\/p>\n<\/li>\n<li>\n<p>\u041a\u0430\u0436\u0434\u044b\u0439 \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u043f\u043e\u043f\u0430\u0434\u0430\u0435\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u0432 heap \u0441\u0432\u043e\u0435\u0439 \u0433\u0440\u0443\u043f\u043f\u044b.<\/p>\n<\/li>\n<li>\n<p>\u0412 \u043a\u043e\u043d\u0446\u0435 \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u043c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442: \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u0433\u0440\u0443\u043f\u043f\u0430 0, \u0437\u0430\u0442\u0435\u043c \u0433\u0440\u0443\u043f\u043f\u0430 1, \u0438 \u0442.\u0434.<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<li>\n<p><strong>SIMD \u0434\u043b\u044f \u043c\u0430\u0441\u0441\u043e\u0432\u043e\u0433\u043e \u0441\u043a\u043e\u0440\u0438\u043d\u0433\u0430<\/strong><\/p>\n<ul>\n<li>\n<p>\u0412\u043c\u0435\u0441\u0442\u043e scalar-\u0446\u0438\u043a\u043b\u0430 \u2014 SIMD-\u0443\u043c\u043d\u043e\u0436\u0435\u043d\u0438\u0435 (AVX2, SSE).<\/p>\n<\/li>\n<li>\n<p>16, 32, 64 \u043f\u0440\u0438\u0437\u043d\u0430\u043a\u0430 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u0437\u0430 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0438\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0439.<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n<h3>\u041e\u0442\u043b\u0438\u0447\u0438\u0435 \u043e\u0442 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0445 \u0440\u0435\u0448\u0435\u043d\u0438\u0439<\/h3>\n<div>\n<div class=\"table\">\n<table>\n<tbody>\n<tr>\n<th>\n<p align=\"left\">\u0420\u0435\u0448\u0435\u043d\u0438\u0435<\/p>\n<\/th>\n<th>\n<p align=\"left\">\u041f\u0440\u0438\u043d\u0446\u0438\u043f<\/p>\n<\/th>\n<th>\n<p align=\"left\">\u0421\u043b\u043e\u0436\u043d\u043e\u0441\u0442\u044c<\/p>\n<\/th>\n<th>\n<p align=\"left\">\u0410\u043b\u043b\u043e\u043a\u0430\u0446\u0438\u0438 \u043d\u0430 \u043a\u0430\u0434\u0440<\/p>\n<\/th>\n<th>\n<p align=\"left\">SIMD<\/p>\n<\/th>\n<th>\n<p align=\"left\">\u0413\u0440\u0443\u043f\u043f\u043e\u0432\u044b\u0435 \u043a\u0432\u043e\u0442\u044b<\/p>\n<\/th>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\"><code>Array.Sort<\/code> + \u0442\u043e\u043f-K<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u041f\u043e\u043b\u043d\u0430\u044f \u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0430<\/p>\n<\/td>\n<td>\n<p align=\"left\">O(N log N)<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0415\u0441\u0442\u044c (\u043c\u0430\u0441\u0441\u0438\u0432\u044b)<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u274c<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u274c<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\"><code>OrderByDescending().Take(K)<\/code> (LINQ)<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u041f\u043e\u043b\u043d\u0430\u044f \u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0430 + \u0434\u0435\u043b\u0435\u0433\u0430\u0442\u044b<\/p>\n<\/td>\n<td>\n<p align=\"left\">O(N log N) + overhead<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u041c\u043d\u043e\u0433\u043e (\u0438\u0442\u0435\u0440\u0430\u0442\u043e\u0440\u044b, \u0434\u0435\u043b\u0435\u0433\u0430\u0442\u044b)<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u274c<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u274c<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">PriorityQueue (\u043f\u0440\u043e\u0441\u0442\u0435\u0439\u0448\u0438\u0439)<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u041e\u0434\u0438\u043d heap<\/p>\n<\/td>\n<td>\n<p align=\"left\">O(N log K)<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0415\u0441\u0442\u044c (\u0443\u0437\u043b\u044b \u043e\u0447\u0435\u0440\u0435\u0434\u0438)<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u274c<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u274c<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">\u0420\u0443\u043a\u043e\u043f\u0438\u0441\u043d\u044b\u0439 selection \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c<\/p>\n<\/td>\n<td>\n<p align=\"left\">quickselect<\/p>\n<\/td>\n<td>\n<p align=\"left\">O(N) \u0432 \u0441\u0440\u0435\u0434\u043d\u0435\u043c<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0417\u0430\u0432\u0438\u0441\u0438\u0442 \u043e\u0442 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u274c<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u274c<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\"><strong>GameBudget.Net<\/strong><\/p>\n<\/td>\n<td>\n<p align=\"left\">Heaps + SIMD<\/p>\n<\/td>\n<td>\n<p align=\"left\">O(N log K) (\u0438\u043b\u0438 O(N log q\u1d4d))<\/p>\n<\/td>\n<td>\n<p align=\"left\"><strong>0 B<\/strong> (caller-\u0431\u0443\u0444\u0435\u0440\u044b)<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u2705<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u2705<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<\/div>\n<p><strong>\u041f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043e \u0440\u0430\u0437\u043b\u0438\u0447\u0438\u044f\u0445<\/strong><\/p>\n<p><strong>1. LINQ \/ Array.Sort<\/strong><\/p>\n<pre><code class=\"cs\">\/\/ \u0422\u0438\u043f\u0438\u0447\u043d\u044b\u0439 LINQ-\u043f\u043e\u0434\u0445\u043e\u0434var topK = items    .Select(i =&gt; new { Id = i.Id, Score = Dot(i.Features, weights) })    .OrderByDescending(x =&gt; x.Score)    .Take(500)    .ToArray(); \/\/ \u041c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0435 \u0430\u043b\u043b\u043e\u043a\u0430\u0446\u0438\u0438<\/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>\u041f\u0440\u043e\u0431\u043b\u0435\u043c\u044b: \u0430\u043b\u043b\u043e\u043a\u0430\u0446\u0438\u0438 \u043d\u0430 \u043a\u0430\u0436\u0434\u044b\u0439 \u044d\u043b\u0435\u043c\u0435\u043d\u0442 (\u0430\u043d\u043e\u043d\u0438\u043c\u043d\u044b\u0439 \u0442\u0438\u043f), \u043f\u043e\u043b\u043d\u0430\u044f \u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0430, \u0434\u0435\u043b\u0435\u0433\u0430\u0442\u044b \u043d\u0430 \u043a\u0430\u0436\u0434\u043e\u043c \u0448\u0430\u0433\u0435.<\/p>\n<p><strong>2. PriorityQueue \u0438\u0437 .NET<\/strong><\/p>\n<pre><code class=\"cs\">var heap = new PriorityQueue&lt;int, float&gt;();for (int i = 0; i &lt; N; i++){    float score = Dot(features[i], weights);    if (heap.Count &lt; K)        heap.Enqueue(i, -score);    else if (score &gt; -heap.PeekPriority())    {        heap.Dequeue();        heap.Enqueue(i, -score);    }}<\/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>\u041f\u0440\u043e\u0431\u043b\u0435\u043c\u044b: \u043d\u0435\u0442 SIMD (\u0441\u043a\u0430\u043b\u044f\u0440\u043d\u044b\u0439 dot), \u0430\u043b\u043b\u043e\u043a\u0430\u0446\u0438\u0438 \u0443\u0437\u043b\u043e\u0432 \u0432\u043d\u0443\u0442\u0440\u0438 PriorityQueue, \u043d\u0435\u0442 \u0433\u0440\u0443\u043f\u043f\u043e\u0432\u044b\u0445 \u043a\u0432\u043e\u0442.<\/p>\n<p><strong>3. QuickSelect (\u0447\u0430\u0441\u0442\u0438\u0447\u043d\u0430\u044f \u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0430)<\/strong><\/p>\n<pre><code class=\"cs\">\/\/ O(N) \u0432 \u0441\u0440\u0435\u0434\u043d\u0435\u043c, \u043d\u043e O(N\u00b2) \u0432 \u0445\u0443\u0434\u0448\u0435\u043cQuickSelect(scores, k);var topK = scores.Take(k);<\/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>\u041f\u0440\u043e\u0431\u043b\u0435\u043c\u044b: \u043c\u043e\u0434\u0438\u0444\u0438\u0446\u0438\u0440\u0443\u0435\u0442 \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u043c\u0430\u0441\u0441\u0438\u0432 (\u043d\u0435\u0436\u0435\u043b\u0430\u0442\u0435\u043b\u044c\u043d\u043e), \u043d\u0435\u0442 SIMD, \u043d\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0433\u0440\u0443\u043f\u043f\u043e\u0432\u044b\u0435 \u043a\u0432\u043e\u0442\u044b, \u043d\u0435\u0442 \u0441\u0442\u0430\u0431\u0438\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u043c\u0435\u0436\u0434\u0443 \u043a\u0430\u0434\u0440\u0430\u043c\u0438.<\/p>\n<h3>\u0411\u044b\u0441\u0442\u0440\u044b\u0439 \u0441\u0442\u0430\u0440\u0442<\/h3>\n<h4>\u0428\u0430\u0433 1. \u041f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043a\u0430 \u0434\u0430\u043d\u043d\u044b\u0445<\/h4>\n<pre><code class=\"cs\">using GameBudget.Net;using SlidingRank.FastOps;int n = 50_000;      \/\/ \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432int d = 32;          \/\/ \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043f\u0440\u0438\u0437\u043d\u0430\u043a\u043e\u0432int k = 1000;        \/\/ \u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0432\u044b\u0431\u0440\u0430\u0442\u044c\/\/ \u041c\u0430\u0442\u0440\u0438\u0446\u0430 \u043f\u0440\u0438\u0437\u043d\u0430\u043a\u043e\u0432: row-major (\u043a\u0430\u0436\u0434\u044b\u0439 \u043e\u0431\u044a\u0435\u043a\u0442 \u2014 d \u0447\u0438\u0441\u0435\u043b)float[] featuresData = new float[n * d];\/\/ \u0412\u0435\u0441\u0430 \u043f\u0440\u0438\u0437\u043d\u0430\u043a\u043e\u0432float[] weights = new float[d];\/\/ ID \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 (\u043e\u043f\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e)int[] ids = new int[n];for (int i = 0; i &lt; n; i++) ids[i] = i;\/\/ ... \u0437\u0430\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u0434\u0430\u043d\u043d\u044b\u0435 ...var features = new EmbeddingMatrix(featuresData, n, d);<\/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<h4>\u0428\u0430\u0433 2. \u0422\u043e\u043f-K \u0431\u0435\u0437 \u0433\u0440\u0443\u043f\u043f\u043e\u0432\u044b\u0445 \u043a\u0432\u043e\u0442<\/h4>\n<pre><code class=\"cs\">using var scheduler = new FrameBudgetScheduler(maxEntities: n);int[] outIds = new int[k];float[] outScores = new float[k];int got = scheduler.SelectTopK(    features: features,    weights: weights,    ids: ids,    k: k,    outIds: outIds,    outScores: outScores);\/\/ outIds \u0438 outScores \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442 \u0442\u043e\u043f-K, \u043e\u0442\u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u043f\u043e \u0443\u0431\u044b\u0432\u0430\u043d\u0438\u044e \u043e\u0446\u0435\u043d\u043a\u0438for (int i = 0; i &lt; got; i++){    Console.WriteLine($\"Rank {i}: ID={outIds[i]}, Score={outScores[i]:F4}\");}<\/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<h4>\u0428\u0430\u0433 3. \u0422\u043e\u043f-K \u0441 \u0433\u0440\u0443\u043f\u043f\u043e\u0432\u044b\u043c\u0438 \u043a\u0432\u043e\u0442\u0430\u043c\u0438<\/h4>\n<pre><code class=\"cs\">int groups = 8;              \/\/ \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0433\u0440\u0443\u043f\u043fint[] groupIds = new int[n]; \/\/ ID \u0433\u0440\u0443\u043f\u043f\u044b \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043e\u0431\u044a\u0435\u043a\u0442\u0430int[] quotas = new int[groups]; \/\/ \u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0432\u044b\u0431\u0440\u0430\u0442\u044c \u0438\u0437 \u043a\u0430\u0436\u0434\u043e\u0439 \u0433\u0440\u0443\u043f\u043f\u044b\/\/ \u041f\u0440\u0438\u043c\u0435\u0440: \u0440\u0430\u0432\u043d\u043e\u043c\u0435\u0440\u043d\u043e\u0435 \u0440\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435for (int g = 0; g &lt; groups; g++)    quotas[g] = k \/ groups;quotas[0] += k - (k \/ groups) * groups; \/\/ \u043e\u0441\u0442\u0430\u0442\u043e\u043a \u0432 \u043f\u0435\u0440\u0432\u0443\u044e \u0433\u0440\u0443\u043f\u043f\u0443using var scheduler = new FrameBudgetScheduler(maxEntities: n, maxGroups: groups);int[] outIds = new int[k];float[] outScores = new float[k];int got = scheduler.SelectWithQuotas(    features: features,    weights: weights,    ids: ids,    groupId: groupIds,    quotas: quotas,    outIds: outIds,    outScores: outScores);\/\/ \u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0441\u0433\u0440\u0443\u043f\u043f\u0438\u0440\u043e\u0432\u0430\u043d: \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u0432\u0441\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u044b \u0433\u0440\u0443\u043f\u043f\u044b 0 (\u043e\u0442\u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u044b \u043f\u043e score), \/\/ \u0437\u0430\u0442\u0435\u043c \u0433\u0440\u0443\u043f\u043f\u044b 1, \u0438 \u0442.\u0434.<\/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>\u041f\u043e\u043b\u043d\u044b\u0439 \u0440\u0430\u0431\u043e\u0447\u0438\u0439 \u043f\u0440\u0438\u043c\u0435\u0440<\/h3>\n<pre><code class=\"cs\">using GameBudget.Net;using SlidingRank.FastOps;public class AILODScheduler{    private FrameBudgetScheduler _scheduler;    private int[] _outIds;    private float[] _outScores;        public AILODScheduler(int maxEntities, int maxK)    {        _scheduler = new FrameBudgetScheduler(maxEntities);        _outIds = new int[maxK];        _outScores = new float[maxK];    }        public int[] SelectTopNpc(        float[] featuresData,  \/\/ row-major: NpcCount \u00d7 FeatureDim        float[] weights,       \/\/ FeatureDim        int[] npcIds,          \/\/ NpcCount        int featureDim,        int k)    {        int npcCount = npcIds.Length;        var features = new EmbeddingMatrix(featuresData, npcCount, featureDim);                int selected = _scheduler.SelectTopK(            features, weights, npcIds, k,            _outIds, _outScores        );                return _outIds[0..selected];    }        public void Dispose() =&gt; _scheduler.Dispose();}\/\/ \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435var scheduler = new AILODScheduler(maxEntities: 50_000, maxK: 2000);\/\/ \u041a\u0430\u0436\u0434\u044b\u0439 \u043a\u0430\u0434\u0440int[] importantNpcs = scheduler.SelectTopNpc(    featuresData: npcFeatures,    weights: importanceWeights,    npcIds: allNpcIds,    featureDim: 32,    k: 500);\/\/ \u041e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u043c AI \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f importantNpcsforeach (int id in importantNpcs){    UpdateAI(id);}<\/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>\u041f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c<\/h3>\n<p>\u0422\u0435\u0441\u0442\u043e\u0432\u044b\u0439 \u0441\u0442\u0435\u043d\u0434: <strong>Intel Core i5-11400F, Windows 11, .NET 8, BenchmarkDotNet<\/strong><\/p>\n<p><strong>\u0422\u043e\u043f-K (dot + \u0441\u0435\u043b\u0435\u043a\u0446\u0438\u044f)<\/strong><\/p>\n<div>\n<div class=\"table\">\n<table>\n<tbody>\n<tr>\n<th>\n<p align=\"left\">\u0421\u0446\u0435\u043d\u0430\u0440\u0438\u0439 (N, D, K)<\/p>\n<\/th>\n<th>\n<p align=\"left\">\u0411\u0430\u0437\u043e\u0432\u044b\u0439 (scalar + \u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0430)<\/p>\n<\/th>\n<th>\n<p align=\"left\">GameBudget.Net (SIMD + heap)<\/p>\n<\/th>\n<th>\n<p align=\"left\">\u0423\u0441\u043a\u043e\u0440\u0435\u043d\u0438\u0435<\/p>\n<\/th>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">10 000, D=32, K=200<\/p>\n<\/td>\n<td>\n<p align=\"left\">709.3 \u03bcs<\/p>\n<\/td>\n<td>\n<p align=\"left\">111.7 \u03bcs<\/p>\n<\/td>\n<td>\n<p align=\"left\"><strong>6.35\u00d7<\/strong><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">50 000, D=32, K=1000<\/p>\n<\/td>\n<td>\n<p align=\"left\">4,256.6 \u03bcs<\/p>\n<\/td>\n<td>\n<p align=\"left\">726.2 \u03bcs<\/p>\n<\/td>\n<td>\n<p align=\"left\"><strong>5.86\u00d7<\/strong><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">200 000, D=16, K=2000<\/p>\n<\/td>\n<td>\n<p align=\"left\">16,157.5 \u03bcs<\/p>\n<\/td>\n<td>\n<p align=\"left\">2,063.4 \u03bcs<\/p>\n<\/td>\n<td>\n<p align=\"left\"><strong>7.83\u00d7<\/strong><\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<\/div>\n<p><strong>\u0413\u0440\u0443\u043f\u043f\u043e\u0432\u044b\u0435 \u043a\u0432\u043e\u0442\u044b (dot + \u0441\u0435\u043b\u0435\u043a\u0446\u0438\u044f \u0441 \u043a\u0432\u043e\u0442\u0430\u043c\u0438)<\/strong><\/p>\n<div>\n<div class=\"table\">\n<table>\n<tbody>\n<tr>\n<th>\n<p align=\"left\">\u0421\u0446\u0435\u043d\u0430\u0440\u0438\u0439 (N, D, G, K)<\/p>\n<\/th>\n<th>\n<p align=\"left\">\u0411\u0430\u0437\u043e\u0432\u044b\u0439 (scalar + \u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0430 + \u0432\u044b\u0431\u043e\u0440)<\/p>\n<\/th>\n<th>\n<p align=\"left\">GameBudget.Net (SIMD + per-group heaps)<\/p>\n<\/th>\n<th>\n<p align=\"left\">\u0423\u0441\u043a\u043e\u0440\u0435\u043d\u0438\u0435<\/p>\n<\/th>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">10 000, D=32, G=8, K=200<\/p>\n<\/td>\n<td>\n<p align=\"left\">1,364.9 \u03bcs<\/p>\n<\/td>\n<td>\n<p align=\"left\">122.7 \u03bcs<\/p>\n<\/td>\n<td>\n<p align=\"left\"><strong>11.12\u00d7<\/strong><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">50 000, D=64, G=16, K=1000<\/p>\n<\/td>\n<td>\n<p align=\"left\">9,553.8 \u03bcs<\/p>\n<\/td>\n<td>\n<p align=\"left\">1,106.0 \u03bcs<\/p>\n<\/td>\n<td>\n<p align=\"left\"><strong>8.64\u00d7<\/strong><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">200 000, D=32, G=32, K=2000<\/p>\n<\/td>\n<td>\n<p align=\"left\">35,216.1 \u03bcs<\/p>\n<\/td>\n<td>\n<p align=\"left\">2,944.0 \u03bcs<\/p>\n<\/td>\n<td>\n<p align=\"left\"><strong>11.96\u00d7<\/strong><\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<\/div>\n<p><strong>\u0427\u0442\u043e \u044d\u0442\u043e \u0437\u043d\u0430\u0447\u0438\u0442 \u0434\u043b\u044f \u0438\u0433\u0440\u044b:<\/strong><\/p>\n<ul>\n<li>\n<p>200 000 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432, \u0432\u044b\u0431\u043e\u0440 \u0442\u043e\u043f-2000 \u0441 \u043a\u0432\u043e\u0442\u0430\u043c\u0438 \u2192 <strong>2.94 \u043c\u0441<\/strong> \u0432\u043c\u0435\u0441\u0442\u043e <strong>35 \u043c\u0441<\/strong><\/p>\n<\/li>\n<li>\n<p>\u042d\u043a\u043e\u043d\u043e\u043c\u0438\u044f ~32 \u043c\u0441 \u043d\u0430 \u043a\u0430\u0434\u0440<\/p>\n<\/li>\n<li>\n<p>\u041f\u0440\u0438 60 FPS \u044d\u0442\u043e \u0440\u0430\u0437\u043d\u0438\u0446\u0430 \u043c\u0435\u0436\u0434\u0443 16 \u043c\u0441 (\u0443\u0441\u043f\u0435\u043b\u0438) \u0438 35 \u043c\u0441 (\u0444\u0440\u0435\u0439\u043c\u0434\u0440\u043e\u043f)<\/p>\n<\/li>\n<\/ul>\n<h3>Zero-\u0430\u043b\u043b\u043e\u043a\u0430\u0446\u0438\u0438: \u043a\u0430\u043a \u044d\u0442\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442<\/h3>\n<p>\u0412 \u043e\u0442\u043b\u0438\u0447\u0438\u0435 \u043e\u0442 LINQ \u0438 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0445 \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0439, GameBudget.Net \u043d\u0435 \u0441\u043e\u0437\u0434\u0430\u0451\u0442 \u043c\u0443\u0441\u043e\u0440\u0430 \u0432 \u0433\u043e\u0440\u044f\u0447\u0435\u043c \u043f\u0443\u0442\u0438.<\/p>\n<p><strong>\u0427\u0442\u043e \u0430\u043b\u043b\u043e\u0446\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u043e\u0434\u0438\u043d \u0440\u0430\u0437 \u043f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 <\/strong><code><strong>FrameBudgetScheduler<\/strong><\/code><strong>:<\/strong><\/p>\n<ul>\n<li>\n<p>\u0412\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0438\u0435 \u0431\u0443\u0444\u0435\u0440\u044b \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445<\/p>\n<\/li>\n<li>\n<p>Heaps \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0439 \u0433\u0440\u0443\u043f\u043f\u044b (\u043f\u0440\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 \u043a\u0432\u043e\u0442)<\/p>\n<\/li>\n<\/ul>\n<p><strong>\u0427\u0442\u043e \u043d\u0435 \u0430\u043b\u043b\u043e\u0446\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u043d\u0430 \u043a\u0430\u0434\u0440:<\/strong><\/p>\n<ul>\n<li>\n<p>\u041c\u0430\u0441\u0441\u0438\u0432\u044b \u0434\u043b\u044f \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u0432 (\u0432\u044b \u043f\u0435\u0440\u0435\u0434\u0430\u0451\u0442\u0435 \u0441\u0432\u043e\u0438)<\/p>\n<\/li>\n<li>\n<p>\u0412\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043c\u0430\u0441\u0441\u0438\u0432\u044b \u0434\u043b\u044f \u043e\u0446\u0435\u043d\u043e\u043a (\u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f)<\/p>\n<\/li>\n<li>\n<p>\u041e\u0431\u044a\u0435\u043a\u0442\u044b \u0432 \u043a\u0443\u0447\u0435 (\u0432\u0441\u0435 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b)<\/p>\n<\/li>\n<\/ul>\n<p><strong>\u041a\u0430\u043a \u0434\u043e\u0441\u0442\u0438\u0447\u044c zero-\u0430\u043b\u043b\u043e\u043a\u0430\u0446\u0438\u0439:<\/strong><\/p>\n<pre><code class=\"cs\">\/\/ \u041f\u043b\u043e\u0445\u043e: \u0430\u043b\u043b\u043e\u043a\u0430\u0446\u0438\u0438 \u043d\u0430 \u043a\u0430\u0434\u0440int[] ids = Enumerable.Range(0, N).ToArray(); \/\/ \u043d\u043e\u0432\u0430\u044f \u0430\u043b\u043b\u043e\u043a\u0430\u0446\u0438\u044ffloat[] scores = new float[N];                 \/\/ \u043d\u043e\u0432\u0430\u044f \u0430\u043b\u043b\u043e\u043a\u0430\u0446\u0438\u044f\/\/ \u0425\u043e\u0440\u043e\u0448\u043e: \u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0431\u0443\u0444\u0435\u0440\u043e\u0432int[] ids = _cachedIds;       \/\/ \u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044ffloat[] scores = _cachedScores; \/\/ \u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044fArray.Clear(scores);           \/\/ \u0431\u0435\u0437 \u0430\u043b\u043b\u043e\u043a\u0430\u0446\u0438\u0439<\/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\u0446\u0435\u043d\u0430\u0440\u0438\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f<\/h3>\n<h4>\u0421\u0446\u0435\u043d\u0430\u0440\u0438\u0439 1: LOD \u0434\u043b\u044f AI (\u0442\u044b\u0441\u044f\u0447\u0438 NPC)<\/h4>\n<p>\u0418\u0437 50 000 NPC \u0432\u044b\u0431\u0438\u0440\u0430\u0435\u043c 1000 \u0441\u0430\u043c\u044b\u0445 \u0432\u0430\u0436\u043d\u044b\u0445 \u0434\u043b\u044f \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f AI.<\/p>\n<pre><code class=\"cs\">\/\/ \u041f\u0440\u0438\u0437\u043d\u0430\u043a\u0438: \u0440\u0430\u0441\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0434\u043e \u0438\u0433\u0440\u043e\u043a\u0430, \u0437\u0434\u043e\u0440\u043e\u0432\u044c\u0435, \u0443\u0433\u0440\u043e\u0437\u0430, \u0443\u0447\u0430\u0441\u0442\u0438\u0435 \u0432 \u0431\u043e\u044efloat[] npcFeatures = new float[npcCount * featureDim];\/\/ ... \u0437\u0430\u043f\u043e\u043b\u043d\u044f\u0435\u043cvar importantNpcs = scheduler.SelectTopK(    features, importanceWeights, npcIds, k: 1000,    outIds, outScores);<\/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<h4>\u0421\u0446\u0435\u043d\u0430\u0440\u0438\u0439 2: \u0410\u043d\u0438\u043c\u0430\u0446\u0438\u0438 \u0441 \u0433\u0440\u0443\u043f\u043f\u043e\u0432\u044b\u043c\u0438 \u043a\u0432\u043e\u0442\u0430\u043c\u0438<\/h4>\n<p>\u0418\u0437 10 000 \u043f\u0435\u0440\u0441\u043e\u043d\u0430\u0436\u0435\u0439 \u0432\u044b\u0431\u0438\u0440\u0430\u0435\u043c 500 \u0434\u043b\u044f \u0434\u0435\u0442\u0430\u043b\u044c\u043d\u044b\u0445 \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u0439, \u043d\u043e \u0441 \u043a\u0432\u043e\u0442\u0430\u043c\u0438: \u043d\u0435 \u0431\u043e\u043b\u0435\u0435 200 \u0432\u0440\u0430\u0433\u043e\u0432, \u043d\u0435 \u0431\u043e\u043b\u0435\u0435 200 \u0441\u043e\u044e\u0437\u043d\u0438\u043a\u043e\u0432, \u043d\u0435 \u0431\u043e\u043b\u0435\u0435 100 \u043d\u0435\u0439\u0442\u0440\u0430\u043b\u043e\u0432.<\/p>\n<pre><code class=\"cs\">int[] quotas = new int[] { 200, 200, 100 }; \/\/ \u0432\u0440\u0430\u0433\u0438, \u0441\u043e\u044e\u0437\u043d\u0438\u043a\u0438, \u043d\u0435\u0439\u0442\u0440\u0430\u043b\u044bint[] selected = scheduler.SelectWithQuotas(    features, animationWeights, characterIds, groupIds, quotas,    outIds, outScores);<\/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<h4>\u0421\u0446\u0435\u043d\u0430\u0440\u0438\u0439 3: VFX \u0438 \u0447\u0430\u0441\u0442\u0438\u0446\u044b<\/h4>\n<p>\u0418\u0437 5000 \u0441\u0438\u0441\u0442\u0435\u043c \u0447\u0430\u0441\u0442\u0438\u0446 \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u043c \u0442\u043e\u043b\u044c\u043a\u043e 300 \u0441\u0430\u043c\u044b\u0445 \u0432\u0430\u0436\u043d\u044b\u0445 (\u0431\u043b\u0438\u0437\u043a\u0438\u0445 \u043a \u043a\u0430\u043c\u0435\u0440\u0435 \u0438\u043b\u0438 \u0441 \u0432\u044b\u0441\u043e\u043a\u043e\u0439 \u0438\u043d\u0442\u0435\u043d\u0441\u0438\u0432\u043d\u043e\u0441\u0442\u044c\u044e).<\/p>\n<h4>\u0421\u0446\u0435\u043d\u0430\u0440\u0438\u0439 4: \u0421\u0435\u0442\u043a\u0430 LOD \u0432 \u043e\u0442\u043a\u0440\u044b\u0442\u043e\u043c \u043c\u0438\u0440\u0435<\/h4>\n<p>\u0418\u0437 200 000 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 \u0432\u044b\u0431\u0438\u0440\u0430\u0435\u043c 10 000 \u0434\u043b\u044f \u0432\u044b\u0441\u043e\u043a\u043e\u0433\u043e \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0430 \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433\u0430.<\/p>\n<h3>\u0421\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u0435 \u0441 \u043a\u043e\u043d\u043a\u0443\u0440\u0435\u043d\u0442\u0430\u043c\u0438 (\u0447\u0435\u0441\u0442\u043d\u043e)<\/h3>\n<div>\n<div class=\"table\">\n<table>\n<tbody>\n<tr>\n<th>\n<p align=\"left\">\u0410\u0441\u043f\u0435\u043a\u0442<\/p>\n<\/th>\n<th>\n<p align=\"left\">Array.Sort<\/p>\n<\/th>\n<th>\n<p align=\"left\">LINQ<\/p>\n<\/th>\n<th>\n<p align=\"left\">PriorityQueue<\/p>\n<\/th>\n<th>\n<p align=\"left\">Unity Burst<\/p>\n<\/th>\n<th>\n<p align=\"left\">GameBudget.Net<\/p>\n<\/th>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">\u0421\u043a\u043e\u0440\u043e\u0441\u0442\u044c (N=200k)<\/p>\n<\/td>\n<td>\n<p align=\"left\">16 \u043c\u0441<\/p>\n<\/td>\n<td>\n<p align=\"left\">25+ \u043c\u0441<\/p>\n<\/td>\n<td>\n<p align=\"left\">8 \u043c\u0441<\/p>\n<\/td>\n<td>\n<p align=\"left\">&lt;1 \u043c\u0441 (Burst)<\/p>\n<\/td>\n<td>\n<p align=\"left\">2 \u043c\u0441<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">SIMD dot<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u274c<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u274c<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u274c<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u2705 (\u0447\u0435\u0440\u0435\u0437 Mathematics)<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u2705<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">Heap-\u0441\u0435\u043b\u0435\u043a\u0446\u0438\u044f<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u274c<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u274c<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u2705 (\u0440\u0443\u043a\u0430\u043c\u0438)<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u274c<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u2705<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">\u0413\u0440\u0443\u043f\u043f\u043e\u0432\u044b\u0435 \u043a\u0432\u043e\u0442\u044b<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u274c<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u274c<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u274c<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u274c<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u2705<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">Zero-\u0430\u043b\u043b\u043e\u043a\u0430\u0446\u0438\u0438<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u274c<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u274c<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u274c<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u2705<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u2705<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">\u0420\u0430\u0431\u043e\u0442\u0430 \u0432\u0435\u0437\u0434\u0435 (.NET)<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u2705<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u2705<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u2705<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u274c (\u0442\u043e\u043b\u044c\u043a\u043e Unity)<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u2705<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">\u041f\u0440\u043e\u0441\u0442\u043e\u0442\u0430 API<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u2705<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u2705<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u274c (\u0440\u0443\u0447\u043d\u0430\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f)<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u274c (\u043d\u0443\u0436\u0435\u043d Burst)<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u2705<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<\/div>\n<p><strong>\u041a\u043e\u0433\u0434\u0430 \u0441\u0442\u043e\u0438\u0442 \u0432\u044b\u0431\u0440\u0430\u0442\u044c Unity Burst \u0432\u043c\u0435\u0441\u0442\u043e GameBudget.Net<\/strong><\/p>\n<ul>\n<li>\n<p>\u0412\u044b \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442\u0435 \u0438\u0441\u043a\u043b\u044e\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0432 Unity \u0438 \u0443\u0436\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0435 Burst.<\/p>\n<\/li>\n<li>\n<p>\u0412\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0435 SIMD-\u0443\u0441\u043a\u043e\u0440\u0435\u043d\u0438\u0435 \u0437\u0430 \u0441\u0447\u0451\u0442 \u043d\u0430\u0442\u0438\u0432\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430.<\/p>\n<\/li>\n<li>\n<p>\u0412\u044b \u0433\u043e\u0442\u043e\u0432\u044b \u043f\u0438\u0441\u0430\u0442\u044c \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u0443\u044e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u0441\u0435\u043b\u0435\u043a\u0442\u043e\u0440\u0430 \u043f\u043e\u0434 \u0441\u0432\u043e\u044e \u0437\u0430\u0434\u0430\u0447\u0443.<\/p>\n<\/li>\n<\/ul>\n<p><strong>\u041a\u043e\u0433\u0434\u0430 \u0441\u0442\u043e\u0438\u0442 \u0432\u044b\u0431\u0440\u0430\u0442\u044c GameBudget.Net<\/strong><\/p>\n<ul>\n<li>\n<p>\u0412\u044b \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442\u0435 \u043d\u0430 \u0447\u0438\u0441\u0442\u043e\u043c .NET (\u043d\u0435 Unity, \u0438\u043b\u0438 Unity \u0431\u0435\u0437 Burst).<\/p>\n<\/li>\n<li>\n<p>\u041d\u0443\u0436\u043d\u0430 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 \u0433\u0440\u0443\u043f\u043f\u043e\u0432\u044b\u0445 \u043a\u0432\u043e\u0442.<\/p>\n<\/li>\n<li>\n<p>\u0412\u0430\u0436\u0435\u043d zero-\u0430\u043b\u043b\u043e\u043a\u0430\u0446\u0438\u0438 API.<\/p>\n<\/li>\n<li>\n<p>\u041d\u0443\u0436\u043d\u0430 \u043f\u0440\u043e\u0441\u0442\u0430\u044f \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044f \u0431\u0435\u0437 \u0438\u0437\u0443\u0447\u0435\u043d\u0438\u044f Burst.<\/p>\n<\/li>\n<\/ul>\n<h3>\u0418\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044f \u0441 Unity<\/h3>\n<pre><code class=\"cs\">using UnityEngine;using GameBudget.Net;using SlidingRank.FastOps;public class AILODManager : MonoBehaviour{    private FrameBudgetScheduler _scheduler;    private int[] _npcIds;    private float[] _featuresData;    private float[] _weights;        void Start()    {        int npcCount = 50000;        int featureDim = 32;                _scheduler = new FrameBudgetScheduler(maxEntities: npcCount);        _npcIds = new int[npcCount];        _featuresData = new float[npcCount * featureDim];        _weights = new float[featureDim];                \/\/ \u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f...    }        void Update()    {        \/\/ \u041e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u043c \u043f\u0440\u0438\u0437\u043d\u0430\u043a\u0438 (\u0440\u0430\u0441\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0434\u043e \u0438\u0433\u0440\u043e\u043a\u0430, \u0437\u0434\u043e\u0440\u043e\u0432\u044c\u0435, \u0443\u0433\u0440\u043e\u0437\u0430)        UpdateFeatures();                \/\/ \u0412\u044b\u0431\u0438\u0440\u0430\u0435\u043c \u0442\u043e\u043f-500 NPC \u0434\u043b\u044f AI-\u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f        int[] outIds = new int[500];        float[] outScores = new float[500];                var features = new EmbeddingMatrix(_featuresData, _npcIds.Length, _weights.Length);                int selected = _scheduler.SelectTopK(            features, _weights, _npcIds, 500,            outIds, outScores        );                \/\/ \u041e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u043c AI \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u044b\u0445        for (int i = 0; i &lt; selected; i++)        {            UpdateAIForNpc(outIds[i]);        }    }        void OnDestroy() =&gt; _scheduler.Dispose();}<\/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>\u0411\u0435\u0441\u043f\u043b\u0430\u0442\u043d\u043e\u0435 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u2014 \u0431\u0435\u0437 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0439. \u041a\u043e\u043c\u043c\u0435\u0440\u0447\u0435\u0441\u043a\u043e\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u043b\u0438\u0446\u0435\u043d\u0437\u0438\u0438.<\/p>\n<p><strong>NuGet:<\/strong> <a href=\"https:\/\/www.nuget.org\/packages\/GameBudget.Net\" rel=\"noopener noreferrer nofollow\">https:\/\/www.nuget.org\/packages\/GameBudget.Net<\/a><\/p>\n<p><strong>GitHub (\u0431\u0435\u043d\u0447\u043c\u0430\u0440\u043a\u0438):<\/strong> <a href=\"https:\/\/github.com\/likeslines-maker\/GameBudget.Net\" rel=\"noopener noreferrer nofollow\">https:\/\/github.com\/likeslines-maker\/GameBudget.Net<\/a><\/p>\n<p>GameBudget.Net \u2014 \u044d\u0442\u043e \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0434\u043b\u044f \u0431\u044b\u0441\u0442\u0440\u043e\u0439 \u0441\u0435\u043b\u0435\u043a\u0446\u0438\u0438 \u0442\u043e\u043f-K \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 \u0441 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u043e\u0439 \u0433\u0440\u0443\u043f\u043f\u043e\u0432\u044b\u0445 \u043a\u0432\u043e\u0442.<\/p>\n<p>\u0412 \u043e\u0442\u043b\u0438\u0447\u0438\u0435 \u043e\u0442 \u043f\u043e\u043b\u043d\u043e\u0439 \u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0438 (Array.Sort, LINQ) \u043e\u043d\u0430:<\/p>\n<ul>\n<li>\n<p>\u0420\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0437\u0430 O(N log K) \u0432\u043c\u0435\u0441\u0442\u043e O(N log N)<\/p>\n<\/li>\n<li>\n<p>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 SIMD \u0434\u043b\u044f \u043c\u0430\u0441\u0441\u043e\u0432\u043e\u0433\u043e \u0441\u043a\u043e\u0440\u0438\u043d\u0433\u0430<\/p>\n<\/li>\n<li>\n<p>\u041d\u0435 \u0441\u043e\u0437\u0434\u0430\u0451\u0442 \u0430\u043b\u043b\u043e\u043a\u0430\u0446\u0438\u0439 \u043d\u0430 \u043a\u0430\u0434\u0440<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0433\u0440\u0443\u043f\u043f\u043e\u0432\u044b\u0435 \u043a\u0432\u043e\u0442\u044b (\u0447\u0435\u0441\u0442\u043d\u043e\u0435 \u0440\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u043c\u0435\u0436\u0434\u0443 \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u044f\u043c\u0438)<\/p>\n<\/li>\n<\/ul>\n<p>\u0412 \u043e\u0442\u043b\u0438\u0447\u0438\u0435 \u043e\u0442 PriorityQueue \u0438\u0437 \u043a\u043e\u0440\u043e\u0431\u043a\u0438:<\/p>\n<ul>\n<li>\n<p>\u0414\u0430\u0451\u0442 \u0433\u043e\u0442\u043e\u0432\u044b\u0439 zero-\u0430\u043b\u043b\u043e\u043a\u0430\u0446\u0438\u0438 API<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0433\u0440\u0443\u043f\u043f\u043e\u0432\u044b\u0435 \u043a\u0432\u043e\u0442\u044b<\/p>\n<\/li>\n<li>\n<p>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 SIMD dot \u0432\u043c\u0435\u0441\u0442\u043e \u0441\u043a\u0430\u043b\u044f\u0440\u043d\u043e\u0433\u043e<\/p>\n<\/li>\n<\/ul>\n<p>\u0412 \u043e\u0442\u043b\u0438\u0447\u0438\u0435 \u043e\u0442 Unity Burst:<\/p>\n<ul>\n<li>\n<p>\u0420\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043d\u0430 \u043b\u044e\u0431\u043e\u043c .NET (\u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e Unity)<\/p>\n<\/li>\n<li>\n<p>\u041d\u0435 \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0438\u0437\u0443\u0447\u0435\u043d\u0438\u044f Burst \u0438 HPC#<\/p>\n<\/li>\n<li>\n<p>\u0414\u0430\u0451\u0442 \u043f\u0440\u043e\u0441\u0442\u043e\u0439 API \u0441 \u0433\u0440\u0443\u043f\u043f\u043e\u0432\u044b\u043c\u0438 \u043a\u0432\u043e\u0442\u0430\u043c\u0438<\/p>\n<\/li>\n<\/ul>\n<p>\u0415\u0441\u043b\u0438 \u0432\u0430\u0448 \u0444\u0440\u0435\u0439\u043c-\u0431\u044e\u0434\u0436\u0435\u0442 \u0441\u0442\u0440\u0430\u0434\u0430\u0435\u0442 \u043e\u0442 \u043f\u043e\u043b\u043d\u043e\u0439 \u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0438 \u0442\u044b\u0441\u044f\u0447 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 \u2014 \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0439\u0442\u0435 GameBudget.Net. \u0421\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0430 200 000 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 \u0437\u0430 16 \u043c\u0441 \u2014 \u044d\u0442\u043e \u0441\u043b\u0438\u0448\u043a\u043e\u043c \u0434\u043e\u0440\u043e\u0433\u043e \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u0432\u044b\u0431\u0440\u043e\u0441\u0438\u0442\u044c 99% \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0430.<\/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\/1042316\/\">https:\/\/habr.com\/ru\/articles\/1042316\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u0412 real-time \u0438\u0433\u0440\u0430\u0445 \u0438 \u0441\u0435\u0440\u0432\u0435\u0440\u0430\u0445 \u0447\u0430\u0441\u0442\u043e \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u0435\u0442 \u0437\u0430\u0434\u0430\u0447\u0430: \u0438\u0437 N \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 \u043d\u0443\u0436\u043d\u043e \u0432\u044b\u0431\u0440\u0430\u0442\u044c K \u043b\u0443\u0447\u0448\u0438\u0445, \u0447\u0442\u043e\u0431\u044b \u043e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u0438\u0445 \u0432 \u044d\u0442\u043e\u043c \u043a\u0430\u0434\u0440\u0435.AI \u0434\u043b\u044f NPC: \u0438\u0437 50 000 \u0432\u0440\u0430\u0433\u043e\u0432 \u043e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e 1000 \u0441\u0430\u043c\u044b\u0445 \u0432\u0430\u0436\u043d\u044b\u0445.\u0410\u043d\u0438\u043c\u0430\u0446\u0438\u0438: \u0438\u0437 10 000 \u043f\u0435\u0440\u0441\u043e\u043d\u0430\u0436\u0435\u0439 \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u0434\u0435\u0442\u0430\u043b\u044c\u043d\u044b\u0435 \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u0438 \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f 200 \u0431\u043b\u0438\u0436\u0430\u0439\u0448\u0438\u0445 \u043a \u043a\u0430\u043c\u0435\u0440\u0435.VFX: \u0438\u0437 5000 \u0447\u0430\u0441\u0442\u0438\u0446 \u043e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u0442\u0435, \u0447\u0442\u043e \u0432 \u043f\u043e\u043b\u0435 \u0437\u0440\u0435\u043d\u0438\u044f.\u0421\u0435\u0442\u043a\u0430 LOD: \u0438\u0437 100 000 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 \u0432\u044b\u0431\u0440\u0430\u0442\u044c 5000 \u0434\u043b\u044f \u0432\u044b\u0441\u043e\u043a\u043e\u0433\u043e \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0430.\u0422\u0438\u043f\u0438\u0447\u043d\u044b\u0439 \u043f\u043e\u0434\u0445\u043e\u0434 \u2014 \u043f\u043e\u0441\u0447\u0438\u0442\u0430\u0442\u044c \u043e\u0446\u0435\u043d\u043a\u0443 \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043e\u0431\u044a\u0435\u043a\u0442\u0430, \u0437\u0430\u0442\u0435\u043c \u043e\u0442\u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432\u0435\u0441\u044c \u043c\u0430\u0441\u0441\u0438\u0432 \u0438 \u0432\u0437\u044f\u0442\u044c \u043f\u0435\u0440\u0432\u044b\u0435 K \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432.\/\/ \u041d\u0430\u0438\u0432\u043d\u044b\u0439 \u043f\u043e\u0434\u0445\u043e\u0434: \u043f\u043e\u043b\u043d\u0430\u044f \u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0430float[] scores = new float[N];for (int i = 0; i &lt; N; i++)    scores[i] = Dot(features[i], weights);Array.Sort(scores, ids); \/\/ O(N log N)\/\/ \u0411\u0435\u0440\u0451\u043c \u043f\u0435\u0440\u0432\u044b\u0435 K\u041f\u0440\u043e\u0431\u043b\u0435\u043c\u0430: \u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0430 200 000 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432 \u0437\u0430\u043d\u0438\u043c\u0430\u0435\u0442 ~16 \u043c\u0441. \u042d\u0442\u043e \u0432\u0435\u0441\u044c \u0431\u044e\u0434\u0436\u0435\u0442 \u043a\u0430\u0434\u0440\u0430 \u043f\u0440\u0438 60 FPS. \u0410 \u0432\u0435\u0434\u044c \u0435\u0449\u0451 \u043d\u0443\u0436\u043d\u043e \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u0442\u044c, \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u0444\u0438\u0437\u0438\u043a\u0443, \u0442\u0438\u043a\u0430\u0442\u044c AI.\u041f\u043e\u0447\u0435\u043c\u0443 \u043f\u043e\u043b\u043d\u0430\u044f \u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0430 \u2014 \u044d\u0442\u043e \u043f\u0435\u0440\u0435\u0431\u043e\u0440\u0421\u043b\u043e\u0436\u043d\u043e\u0441\u0442\u044c O(N log N). \u0414\u043b\u044f N = 200 000 \u044d\u0442\u043e \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e 200 000 \u00d7 18 = 3.6 \u043c\u043b\u043d \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u0439. \u041f\u043b\u044e\u0441 \u0430\u043b\u043b\u043e\u043a\u0430\u0446\u0438\u0438 \u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u043c\u0430\u0441\u0441\u0438\u0432\u043e\u0432. \u041f\u043b\u044e\u0441 GC-\u043f\u0430\u0443\u0437\u044b.\u0410 \u0432\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0432\u0441\u0435\u0433\u043e K = 2000 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432. \u0412\u044b \u0432\u044b\u0431\u0440\u0430\u0441\u044b\u0432\u0430\u0435\u0442\u0435 198 000 \u043e\u0442c\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432. \u042d\u0442\u043e 99% \u043f\u043e\u0442\u0440\u0430\u0447\u0435\u043d\u043d\u043e\u0439 \u0440\u0430\u0431\u043e\u0442\u044b \u0432\u043f\u0443\u0441\u0442\u0443\u044e.\u0414\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u0430\u044f \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430: \u0433\u0440\u0443\u043f\u043f\u043e\u0432\u044b\u0435 \u043a\u0432\u043e\u0442\u044b\u0427\u0430\u0441\u0442\u043e \u043d\u0443\u0436\u043d\u043e \u043d\u0435 \u043f\u0440\u043e\u0441\u0442\u043e \u0442\u043e\u043f-K, \u0430 \u0441\u043f\u0440\u0430\u0432\u0435\u0434\u043b\u0438\u0432\u043e\u0435 \u0440\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u043c\u0435\u0436\u0434\u0443 \u0433\u0440\u0443\u043f\u043f\u0430\u043c\u0438:\u0410\u043d\u0438\u043c\u0430\u0446\u0438\u0438: \u043d\u0435 \u0431\u043e\u043b\u0435\u0435 200 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432AI: \u043d\u0435 \u0431\u043e\u043b\u0435\u0435 500 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432VFX: \u043d\u0435 \u0431\u043e\u043b\u0435\u0435 300 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432\u0424\u0438\u0437\u0438\u043a\u0430: \u043d\u0435 \u0431\u043e\u043b\u0435\u0435 200 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432\u0421\u0443\u043c\u043c\u0430 \u043a\u0432\u043e\u0442 = K = 1200. \u041d\u043e \u0435\u0441\u043b\u0438 \u043e\u0442\u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043e\u0431\u0449\u0438\u0439 \u0441\u043f\u0438\u0441\u043e\u043a, \u043e\u0434\u043d\u0430 \u0433\u0440\u0443\u043f\u043f\u0430 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0432\u0440\u0430\u0433\u0438) \u043c\u043e\u0436\u0435\u0442 \u0437\u0430\u043d\u044f\u0442\u044c \u0432\u0441\u0435 \u0442\u043e\u043f-1200 \u043c\u0435\u0441\u0442, \u0430 \u0434\u0440\u0443\u0433\u0438\u0435 \u0433\u0440\u0443\u043f\u043f\u044b (\u0441\u043e\u044e\u0437\u043d\u0438\u043a\u0438, \u043d\u0435\u0439\u0442\u0440\u0430\u043b\u044b) \u043d\u0435 \u043f\u043e\u043b\u0443\u0447\u0430\u0442 \u043d\u0438\u0447\u0435\u0433\u043e.\u041f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435: \u043e\u0442\u043e\u0431\u0440\u0430\u0442\u044c \u0442\u043e\u043f-K \u0441 \u0443\u0447\u0451\u0442\u043e\u043c \u043a\u0432\u043e\u0442 \u043d\u0430 \u0433\u0440\u0443\u043f\u043f\u0443. \u041d\u043e \u043a\u0430\u043a \u044d\u0442\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0431\u0435\u0437 \u043c\u043d\u043e\u0433\u043e\u043a\u0440\u0430\u0442\u043d\u043e\u0439 \u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0438?\u0420\u0435\u0448\u0435\u043d\u0438\u0435: SIMD + \u0441\u0435\u043b\u0435\u043a\u0446\u0438\u044f \u0431\u0435\u0437 \u043f\u043e\u043b\u043d\u043e\u0439 \u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0438GameBudget.Net \u2014 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0434\u043b\u044f .NET 8.0+, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0440\u0435\u0448\u0430\u0435\u0442 \u043e\u0431\u0435 \u0437\u0430\u0434\u0430\u0447\u0438:\u0422\u043e\u043f-K \u0447\u0435\u0440\u0435\u0437 heap-\u0441\u0435\u043b\u0435\u043a\u0446\u0438\u044e: O(N log K) \u0432\u043c\u0435\u0441\u0442\u043e O(N log N)\u0413\u0440\u0443\u043f\u043f\u043e\u0432\u044b\u0435 \u043a\u0432\u043e\u0442\u044b \u0447\u0435\u0440\u0435\u0437 per-group heap: O(N log q\u1d4d) (\u0433\u0434\u0435 q\u1d4d \u2014 \u043a\u0432\u043e\u0442\u0430 \u0433\u0440\u0443\u043f\u043f\u044b)SIMD-\u0443\u043c\u043d\u043e\u0436\u0435\u043d\u0438\u0435 \u043c\u0430\u0442\u0440\u0438\u0446 \u0434\u043b\u044f \u0441\u043a\u043e\u0440\u0438\u043d\u0433\u0430 \u0447\u0435\u0440\u0435\u0437 SlidingRank.FastOpsdotnet add package GameBudget.Net &#8212;version 1.0.0\u041a\u043b\u044e\u0447\u0435\u0432\u044b\u0435 \u0438\u0434\u0435\u0438Heap-\u0441\u0435\u043b\u0435\u043a\u0446\u0438\u044f (\u0431\u0435\u0437 \u043f\u043e\u043b\u043d\u043e\u0439 \u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0438)\u041f\u0440\u043e\u0445\u043e\u0434\u0438\u043c \u043f\u043e \u0432\u0441\u0435\u043c N \u043e\u0431\u044a\u0435\u043a\u0442\u0430\u043c.\u041f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u043c min-heap \u0440\u0430\u0437\u043c\u0435\u0440\u043e\u043c K.\u0415\u0441\u043b\u0438 \u043d\u043e\u0432\u044b\u0439 \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u043b\u0443\u0447\u0448\u0435 \u0445\u0443\u0434\u0448\u0435\u0433\u043e \u0432 \u043a\u0443\u0447\u0435 \u2014 \u0437\u0430\u043c\u0435\u043d\u044f\u0435\u043c.\u0412 \u043a\u043e\u043d\u0446\u0435 heap \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0442\u043e\u043f-K, \u0438\u0437\u0432\u043b\u0435\u043a\u0430\u0435\u043c \u0432 \u043e\u0442\u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u043c \u043f\u043e\u0440\u044f\u0434\u043a\u0435.Per-group \u0441\u0435\u043b\u0435\u043a\u0446\u0438\u044f \u0441 \u043a\u0432\u043e\u0442\u0430\u043c\u0438\u0414\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0439 \u0433\u0440\u0443\u043f\u043f\u044b \u0441\u0432\u043e\u0439 min-heap \u0440\u0430\u0437\u043c\u0435\u0440\u043e\u043c \u0441 \u043a\u0432\u043e\u0442\u0443 \u0433\u0440\u0443\u043f\u043f\u044b.\u041a\u0430\u0436\u0434\u044b\u0439 \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u043f\u043e\u043f\u0430\u0434\u0430\u0435\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u0432 heap \u0441\u0432\u043e\u0435\u0439 \u0433\u0440\u0443\u043f\u043f\u044b.\u0412 \u043a\u043e\u043d\u0446\u0435 \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u043c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442: \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u0433\u0440\u0443\u043f\u043f\u0430 0, \u0437\u0430\u0442\u0435\u043c \u0433\u0440\u0443\u043f\u043f\u0430 1, \u0438 \u0442.\u0434.SIMD \u0434\u043b\u044f \u043c\u0430\u0441\u0441\u043e\u0432\u043e\u0433\u043e \u0441\u043a\u043e\u0440\u0438\u043d\u0433\u0430\u0412\u043c\u0435\u0441\u0442\u043e scalar-\u0446\u0438\u043a\u043b\u0430 \u2014 SIMD-\u0443\u043c\u043d\u043e\u0436\u0435\u043d\u0438\u0435 (AVX2, SSE).16, 32, 64 \u043f\u0440\u0438\u0437\u043d\u0430\u043a\u0430 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u0437\u0430 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0438\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0439.\u041e\u0442\u043b\u0438\u0447\u0438\u0435 \u043e\u0442 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0445 \u0440\u0435\u0448\u0435\u043d\u0438\u0439\u0420\u0435\u0448\u0435\u043d\u0438\u0435\u041f\u0440\u0438\u043d\u0446\u0438\u043f\u0421\u043b\u043e\u0436\u043d\u043e\u0441\u0442\u044c\u0410\u043b\u043b\u043e\u043a\u0430\u0446\u0438\u0438 \u043d\u0430 \u043a\u0430\u0434\u0440SIMD\u0413\u0440\u0443\u043f\u043f\u043e\u0432\u044b\u0435 \u043a\u0432\u043e\u0442\u044bArray.Sort + \u0442\u043e\u043f-K\u041f\u043e\u043b\u043d\u0430\u044f \u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0430O(N log N)\u0415\u0441\u0442\u044c (\u043c\u0430\u0441\u0441\u0438\u0432\u044b)\u274c\u274cOrderByDescending().Take(K) (LINQ)\u041f\u043e\u043b\u043d\u0430\u044f \u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0430 + \u0434\u0435\u043b\u0435\u0433\u0430\u0442\u044bO(N log N) + overhead\u041c\u043d\u043e\u0433\u043e (\u0438\u0442\u0435\u0440\u0430\u0442\u043e\u0440\u044b, \u0434\u0435\u043b\u0435\u0433\u0430\u0442\u044b)\u274c\u274cPriorityQueue (\u043f\u0440\u043e\u0441\u0442\u0435\u0439\u0448\u0438\u0439)\u041e\u0434\u0438\u043d heapO(N log K)\u0415\u0441\u0442\u044c (\u0443\u0437\u043b\u044b \u043e\u0447\u0435\u0440\u0435\u0434\u0438)\u274c\u274c\u0420\u0443\u043a\u043e\u043f\u0438\u0441\u043d\u044b\u0439 selection \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043cquickselectO(N) \u0432 \u0441\u0440\u0435\u0434\u043d\u0435\u043c\u0417\u0430\u0432\u0438\u0441\u0438\u0442 \u043e\u0442 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438\u274c\u274cGameBudget.NetHeaps + SIMDO(N log K) (\u0438\u043b\u0438 O(N log q\u1d4d))0 B (caller-\u0431\u0443\u0444\u0435\u0440\u044b)\u2705\u2705\u041f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043e \u0440\u0430\u0437\u043b\u0438\u0447\u0438\u044f\u04451. LINQ \/ Array.Sort\/\/ \u0422\u0438\u043f\u0438\u0447\u043d\u044b\u0439 LINQ-\u043f\u043e\u0434\u0445\u043e\u0434var topK = items    .Select(i =&gt; new { Id = i.Id, Score = Dot(i.Features, weights) })    .OrderByDescending(x =&gt; x.Score)    .Take(500)    .ToArray(); \/\/ \u041c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0435 \u0430\u043b\u043b\u043e\u043a\u0430\u0446\u0438\u0438\u041f\u0440\u043e\u0431\u043b\u0435\u043c\u044b: \u0430\u043b\u043b\u043e\u043a\u0430\u0446\u0438\u0438 \u043d\u0430 \u043a\u0430\u0436\u0434\u044b\u0439 \u044d\u043b\u0435\u043c\u0435\u043d\u0442 (\u0430\u043d\u043e\u043d\u0438\u043c\u043d\u044b\u0439 \u0442\u0438\u043f), \u043f\u043e\u043b\u043d\u0430\u044f \u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0430, \u0434\u0435\u043b\u0435\u0433\u0430\u0442\u044b \u043d\u0430 \u043a\u0430\u0436\u0434\u043e\u043c \u0448\u0430\u0433\u0435.2. PriorityQueue \u0438\u0437 .NETvar heap = new PriorityQueue&lt;int, float&gt;();for (int i = 0; i &lt; N; i++){    float score = Dot(features[i], weights);    if (heap.Count &lt; K)        heap.Enqueue(i, -score);    else if (score &gt; -heap.PeekPriority())    {        heap.Dequeue();        heap.Enqueue(i, -score);    }}\u041f\u0440\u043e\u0431\u043b\u0435\u043c\u044b: \u043d\u0435\u0442 SIMD (\u0441\u043a\u0430\u043b\u044f\u0440\u043d\u044b\u0439 dot), \u0430\u043b\u043b\u043e\u043a\u0430\u0446\u0438\u0438 \u0443\u0437\u043b\u043e\u0432 \u0432\u043d\u0443\u0442\u0440\u0438 PriorityQueue, \u043d\u0435\u0442 \u0433\u0440\u0443\u043f\u043f\u043e\u0432\u044b\u0445 \u043a\u0432\u043e\u0442.3. QuickSelect (\u0447\u0430\u0441\u0442\u0438\u0447\u043d\u0430\u044f \u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0430)\/\/ O(N) \u0432 \u0441\u0440\u0435\u0434\u043d\u0435\u043c, \u043d\u043e O(N\u00b2) \u0432 \u0445\u0443\u0434\u0448\u0435\u043cQuickSelect(scores, k);var topK = scores.Take(k);\u041f\u0440\u043e\u0431\u043b\u0435\u043c\u044b: \u043c\u043e\u0434\u0438\u0444\u0438\u0446\u0438\u0440\u0443\u0435\u0442 \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u043c\u0430\u0441\u0441\u0438\u0432 (\u043d\u0435\u0436\u0435\u043b\u0430\u0442\u0435\u043b\u044c\u043d\u043e), \u043d\u0435\u0442 SIMD, \u043d\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0433\u0440\u0443\u043f\u043f\u043e\u0432\u044b\u0435 \u043a\u0432\u043e\u0442\u044b, \u043d\u0435\u0442 \u0441\u0442\u0430\u0431\u0438\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u043c\u0435\u0436\u0434\u0443 \u043a\u0430\u0434\u0440\u0430\u043c\u0438.\u0411\u044b\u0441\u0442\u0440\u044b\u0439 \u0441\u0442\u0430\u0440\u0442\u0428\u0430\u0433 1. \u041f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043a\u0430 \u0434\u0430\u043d\u043d\u044b\u0445using GameBudget.Net;using SlidingRank.FastOps;int n = 50_000;      \/\/ \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432int d = 32;          \/\/ \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043f\u0440\u0438\u0437\u043d\u0430\u043a\u043e\u0432int k = 1000;        \/\/ \u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0432\u044b\u0431\u0440\u0430\u0442\u044c\/\/ \u041c\u0430\u0442\u0440\u0438\u0446\u0430 \u043f\u0440\u0438\u0437\u043d\u0430\u043a\u043e\u0432: row-major (\u043a\u0430\u0436\u0434\u044b\u0439 \u043e\u0431\u044a\u0435\u043a\u0442 \u2014 d \u0447\u0438\u0441\u0435\u043b)float[] featuresData = new float[n * d];\/\/ \u0412\u0435\u0441\u0430 \u043f\u0440\u0438\u0437\u043d\u0430\u043a\u043e\u0432float[] weights = new float[d];\/\/ ID \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 (\u043e\u043f\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e)int[] ids = new int[n];for (int i = 0; i &lt; n; i++) ids[i] = i;\/\/ &#8230; \u0437\u0430\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u0434\u0430\u043d\u043d\u044b\u0435 &#8230;var features = new EmbeddingMatrix(featuresData, n, d);\u0428\u0430\u0433 2. \u0422\u043e\u043f-K \u0431\u0435\u0437 \u0433\u0440\u0443\u043f\u043f\u043e\u0432\u044b\u0445 \u043a\u0432\u043e\u0442using var scheduler = new FrameBudgetScheduler(maxEntities: n);int[] outIds = new int[k];float[] outScores = new float[k];int got = scheduler.SelectTopK(    features: features,    weights: weights,    ids: ids,    k: k,    outIds: outIds,    outScores: outScores);\/\/ outIds \u0438 outScores \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442 \u0442\u043e\u043f-K, \u043e\u0442\u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u043f\u043e \u0443\u0431\u044b\u0432\u0430\u043d\u0438\u044e \u043e\u0446\u0435\u043d\u043a\u0438for (int i = 0; i &lt; got; i++){    Console.WriteLine($&#187;Rank {i}: ID={outIds[i]}, Score={outScores[i]:F4}&#187;);}\u0428\u0430\u0433 3. \u0422\u043e\u043f-K \u0441 \u0433\u0440\u0443\u043f\u043f\u043e\u0432\u044b\u043c\u0438 \u043a\u0432\u043e\u0442\u0430\u043c\u0438int groups = 8;              \/\/ \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0433\u0440\u0443\u043f\u043fint[] groupIds = new int[n]; \/\/ ID \u0433\u0440\u0443\u043f\u043f\u044b \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043e\u0431\u044a\u0435\u043a\u0442\u0430int[] quotas = new int[groups]; \/\/ \u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0432\u044b\u0431\u0440\u0430\u0442\u044c \u0438\u0437 \u043a\u0430\u0436\u0434\u043e\u0439 \u0433\u0440\u0443\u043f\u043f\u044b\/\/ \u041f\u0440\u0438\u043c\u0435\u0440: \u0440\u0430\u0432\u043d\u043e\u043c\u0435\u0440\u043d\u043e\u0435 \u0440\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435for (int g = 0; g &lt; groups; g++)    quotas[g] = k \/ groups;quotas[0] += k &#8212; (k \/ groups) * groups; \/\/ \u043e\u0441\u0442\u0430\u0442\u043e\u043a \u0432 \u043f\u0435\u0440\u0432\u0443\u044e \u0433\u0440\u0443\u043f\u043f\u0443using var scheduler = new FrameBudgetScheduler(maxEntities: n, maxGroups: groups);int[] outIds = new int[k];float[] outScores = new float[k];int got = scheduler.SelectWithQuotas(    features: features,    weights: weights,    ids: ids,    groupId: groupIds,    quotas: quotas,    outIds: outIds,    outScores: outScores);\/\/ \u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0441\u0433\u0440\u0443\u043f\u043f\u0438\u0440\u043e\u0432\u0430\u043d: \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u0432\u0441\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u044b \u0433\u0440\u0443\u043f\u043f\u044b 0 (\u043e\u0442\u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u044b \u043f\u043e score), \/\/ \u0437\u0430\u0442\u0435\u043c \u0433\u0440\u0443\u043f\u043f\u044b 1, \u0438 \u0442.\u0434.\u041f\u043e\u043b\u043d\u044b\u0439 \u0440\u0430\u0431\u043e\u0447\u0438\u0439 \u043f\u0440\u0438\u043c\u0435\u0440using GameBudget.Net;using SlidingRank.FastOps;public class AILODScheduler{    private FrameBudgetScheduler _scheduler;    private int[] _outIds;    private float[] _outScores;        public AILODScheduler(int maxEntities, int maxK)    {        _scheduler = new FrameBudgetScheduler(maxEntities);        _outIds = new int[maxK];        _outScores = new float[maxK];    }        public int[] SelectTopNpc(        float[] featuresData,  \/\/ row-major: NpcCount \u00d7 FeatureDim        float[] weights,       \/\/ FeatureDim        int[] npcIds,          \/\/ NpcCount        int featureDim,        int k)    {        int npcCount = npcIds.Length;        var features = new EmbeddingMatrix(featuresData, npcCount, featureDim);                int selected = _scheduler.SelectTopK(            features, weights, npcIds, k,            _outIds, _outScores        );                return _outIds[0..selected];    }        public void Dispose() =&gt; _scheduler.Dispose();}\/\/ \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435var scheduler = new AILODScheduler(maxEntities: 50_000, maxK: 2000);\/\/ \u041a\u0430\u0436\u0434\u044b\u0439 \u043a\u0430\u0434\u0440int[] importantNpcs = scheduler.SelectTopNpc(    featuresData: npcFeatures,    weights: importanceWeights,    npcIds: allNpcIds,    featureDim: 32,    k: 500);\/\/ \u041e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u043c AI \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f importantNpcsforeach (int id in importantNpcs){    UpdateAI(id);}\u041f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c\u0422\u0435\u0441\u0442\u043e\u0432\u044b\u0439 \u0441\u0442\u0435\u043d\u0434: Intel Core i5-11400F, Windows 11, .NET 8, BenchmarkDotNet\u0422\u043e\u043f-K (dot + \u0441\u0435\u043b\u0435\u043a\u0446\u0438\u044f)\u0421\u0446\u0435\u043d\u0430\u0440\u0438\u0439 (N, D, K)\u0411\u0430\u0437\u043e\u0432\u044b\u0439 (scalar + \u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0430)GameBudget.Net (SIMD + heap)\u0423\u0441\u043a\u043e\u0440\u0435\u043d\u0438\u043510 000, D=32, K=200709.3 \u03bcs111.7 \u03bcs6.35\u00d750 000, D=32, K=10004,256.6 \u03bcs726.2 \u03bcs5.86\u00d7200 000, D=16, K=200016,157.5 \u03bcs2,063.4 \u03bcs7.83\u00d7\u0413\u0440\u0443\u043f\u043f\u043e\u0432\u044b\u0435 \u043a\u0432\u043e\u0442\u044b (dot + \u0441\u0435\u043b\u0435\u043a\u0446\u0438\u044f \u0441 \u043a\u0432\u043e\u0442\u0430\u043c\u0438)\u0421\u0446\u0435\u043d\u0430\u0440\u0438\u0439 (N, D, G, K)\u0411\u0430\u0437\u043e\u0432\u044b\u0439 (scalar + \u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0430 + \u0432\u044b\u0431\u043e\u0440)GameBudget.Net (SIMD + per-group heaps)\u0423\u0441\u043a\u043e\u0440\u0435\u043d\u0438\u043510 000, D=32, G=8, K=2001,364.9 \u03bcs122.7 \u03bcs11.12\u00d750 000, D=64, G=16, K=10009,553.8 \u03bcs1,106.0 \u03bcs8.64\u00d7200 000, D=32, G=32, K=200035,216.1 \u03bcs2,944.0 \u03bcs11.96\u00d7\u0427\u0442\u043e \u044d\u0442\u043e \u0437\u043d\u0430\u0447\u0438\u0442 \u0434\u043b\u044f \u0438\u0433\u0440\u044b:200 000 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432, \u0432\u044b\u0431\u043e\u0440 \u0442\u043e\u043f-2000 \u0441 \u043a\u0432\u043e\u0442\u0430\u043c\u0438 \u2192 2.94 \u043c\u0441 \u0432\u043c\u0435\u0441\u0442\u043e 35 \u043c\u0441\u042d\u043a\u043e\u043d\u043e\u043c\u0438\u044f ~32 \u043c\u0441 \u043d\u0430 \u043a\u0430\u0434\u0440\u041f\u0440\u0438 60 FPS \u044d\u0442\u043e \u0440\u0430\u0437\u043d\u0438\u0446\u0430 \u043c\u0435\u0436\u0434\u0443 16 \u043c\u0441 (\u0443\u0441\u043f\u0435\u043b\u0438) \u0438 35 \u043c\u0441 (\u0444\u0440\u0435\u0439\u043c\u0434\u0440\u043e\u043f)Zero-\u0430\u043b\u043b\u043e\u043a\u0430\u0446\u0438\u0438: \u043a\u0430\u043a \u044d\u0442\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442\u0412 \u043e\u0442\u043b\u0438\u0447\u0438\u0435 \u043e\u0442 LINQ \u0438 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0445 \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0439, GameBudget.Net \u043d\u0435 \u0441\u043e\u0437\u0434\u0430\u0451\u0442 \u043c\u0443\u0441\u043e\u0440\u0430 \u0432 \u0433\u043e\u0440\u044f\u0447\u0435\u043c \u043f\u0443\u0442\u0438.\u0427\u0442\u043e \u0430\u043b\u043b\u043e\u0446\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u043e\u0434\u0438\u043d \u0440\u0430\u0437 \u043f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 FrameBudgetScheduler:\u0412\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0438\u0435 \u0431\u0443\u0444\u0435\u0440\u044b \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445Heaps \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0439 \u0433\u0440\u0443\u043f\u043f\u044b (\u043f\u0440\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 \u043a\u0432\u043e\u0442)\u0427\u0442\u043e \u043d\u0435 \u0430\u043b\u043b\u043e\u0446\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u043d\u0430 \u043a\u0430\u0434\u0440:\u041c\u0430\u0441\u0441\u0438\u0432\u044b \u0434\u043b\u044f \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u0432 (\u0432\u044b \u043f\u0435\u0440\u0435\u0434\u0430\u0451\u0442\u0435 \u0441\u0432\u043e\u0438)\u0412\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043c\u0430\u0441\u0441\u0438\u0432\u044b \u0434\u043b\u044f \u043e\u0446\u0435\u043d\u043e\u043a (\u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f)\u041e\u0431\u044a\u0435\u043a\u0442\u044b \u0432 \u043a\u0443\u0447\u0435 (\u0432\u0441\u0435 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b)\u041a\u0430\u043a \u0434\u043e\u0441\u0442\u0438\u0447\u044c zero-\u0430\u043b\u043b\u043e\u043a\u0430\u0446\u0438\u0439:\/\/ \u041f\u043b\u043e\u0445\u043e: \u0430\u043b\u043b\u043e\u043a\u0430\u0446\u0438\u0438 \u043d\u0430 \u043a\u0430\u0434\u0440int[] ids = Enumerable.Range(0, N).ToArray(); \/\/ \u043d\u043e\u0432\u0430\u044f \u0430\u043b\u043b\u043e\u043a\u0430\u0446\u0438\u044ffloat[] scores = new float[N];                 \/\/ \u043d\u043e\u0432\u0430\u044f \u0430\u043b\u043b\u043e\u043a\u0430\u0446\u0438\u044f\/\/ \u0425\u043e\u0440\u043e\u0448\u043e: \u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0431\u0443\u0444\u0435\u0440\u043e\u0432int[] ids = _cachedIds;       \/\/ \u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044ffloat[] scores = _cachedScores; \/\/ \u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044fArray.Clear(scores);           \/\/ \u0431\u0435\u0437 \u0430\u043b\u043b\u043e\u043a\u0430\u0446\u0438\u0439\u0421\u0446\u0435\u043d\u0430\u0440\u0438\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f\u0421\u0446\u0435\u043d\u0430\u0440\u0438\u0439 1: LOD \u0434\u043b\u044f AI (\u0442\u044b\u0441\u044f\u0447\u0438 NPC)\u0418\u0437 50 000 NPC \u0432\u044b\u0431\u0438\u0440\u0430\u0435\u043c 1000 \u0441\u0430\u043c\u044b\u0445 \u0432\u0430\u0436\u043d\u044b\u0445 \u0434\u043b\u044f \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f AI.\/\/ \u041f\u0440\u0438\u0437\u043d\u0430\u043a\u0438: \u0440\u0430\u0441\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0434\u043e \u0438\u0433\u0440\u043e\u043a\u0430, \u0437\u0434\u043e\u0440\u043e\u0432\u044c\u0435, \u0443\u0433\u0440\u043e\u0437\u0430, \u0443\u0447\u0430\u0441\u0442\u0438\u0435 \u0432 \u0431\u043e\u044efloat[] npcFeatures = new float[npcCount * featureDim];\/\/ &#8230; \u0437\u0430\u043f\u043e\u043b\u043d\u044f\u0435\u043cvar importantNpcs = scheduler.SelectTopK(    features, importanceWeights, npcIds, k: 1000,    outIds, outScores);\u0421\u0446\u0435\u043d\u0430\u0440\u0438\u0439 2: \u0410\u043d\u0438\u043c\u0430\u0446\u0438\u0438 \u0441 \u0433\u0440\u0443\u043f\u043f\u043e\u0432\u044b\u043c\u0438 \u043a\u0432\u043e\u0442\u0430\u043c\u0438\u0418\u0437 10 000 \u043f\u0435\u0440\u0441\u043e\u043d\u0430\u0436\u0435\u0439 \u0432\u044b\u0431\u0438\u0440\u0430\u0435\u043c 500 \u0434\u043b\u044f \u0434\u0435\u0442\u0430\u043b\u044c\u043d\u044b\u0445 \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u0439, \u043d\u043e \u0441 \u043a\u0432\u043e\u0442\u0430\u043c\u0438: \u043d\u0435 \u0431\u043e\u043b\u0435\u0435 200 \u0432\u0440\u0430\u0433\u043e\u0432, \u043d\u0435 \u0431\u043e\u043b\u0435\u0435 200 \u0441\u043e\u044e\u0437\u043d\u0438\u043a\u043e\u0432, \u043d\u0435 \u0431\u043e\u043b\u0435\u0435 100 \u043d\u0435\u0439\u0442\u0440\u0430\u043b\u043e\u0432.int[] quotas = new int[] { 200, 200, 100 }; \/\/ \u0432\u0440\u0430\u0433\u0438, \u0441\u043e\u044e\u0437\u043d\u0438\u043a\u0438, \u043d\u0435\u0439\u0442\u0440\u0430\u043b\u044bint[] selected = scheduler.SelectWithQuotas(    features, animationWeights, characterIds, groupIds, quotas,    outIds, outScores);\u0421\u0446\u0435\u043d\u0430\u0440\u0438\u0439 3: VFX \u0438 \u0447\u0430\u0441\u0442\u0438\u0446\u044b\u0418\u0437 5000 \u0441\u0438\u0441\u0442\u0435\u043c \u0447\u0430\u0441\u0442\u0438\u0446 \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u043c \u0442\u043e\u043b\u044c\u043a\u043e 300 \u0441\u0430\u043c\u044b\u0445 \u0432\u0430\u0436\u043d\u044b\u0445 (\u0431\u043b\u0438\u0437\u043a\u0438\u0445 \u043a \u043a\u0430\u043c\u0435\u0440\u0435 \u0438\u043b\u0438 \u0441 \u0432\u044b\u0441\u043e\u043a\u043e\u0439 \u0438\u043d\u0442\u0435\u043d\u0441\u0438\u0432\u043d\u043e\u0441\u0442\u044c\u044e).\u0421\u0446\u0435\u043d\u0430\u0440\u0438\u0439 4: \u0421\u0435\u0442\u043a\u0430 LOD \u0432 \u043e\u0442\u043a\u0440\u044b\u0442\u043e\u043c \u043c\u0438\u0440\u0435\u0418\u0437 200 000 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 \u0432\u044b\u0431\u0438\u0440\u0430\u0435\u043c 10 000 \u0434\u043b\u044f \u0432\u044b\u0441\u043e\u043a\u043e\u0433\u043e \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0430 \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433\u0430.\u0421\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u0435 \u0441 \u043a\u043e\u043d\u043a\u0443\u0440\u0435\u043d\u0442\u0430\u043c\u0438 (\u0447\u0435\u0441\u0442\u043d\u043e)\u0410\u0441\u043f\u0435\u043a\u0442Array.SortLINQPriorityQueueUnity BurstGameBudget.Net\u0421\u043a\u043e\u0440\u043e\u0441\u0442\u044c (N=200k)16 \u043c\u044125+ \u043c\u04418 \u043c\u0441&lt;1 \u043c\u0441 (Burst)2 \u043c\u0441SIMD dot\u274c\u274c\u274c\u2705 (\u0447\u0435\u0440\u0435\u0437 Mathematics)\u2705Heap-\u0441\u0435\u043b\u0435\u043a\u0446\u0438\u044f\u274c\u274c\u2705 (\u0440\u0443\u043a\u0430\u043c\u0438)\u274c\u2705\u0413\u0440\u0443\u043f\u043f\u043e\u0432\u044b\u0435&#8230;<\/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-481959","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/481959","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=481959"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/481959\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=481959"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=481959"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=481959"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}