{"id":389291,"date":"2024-06-29T08:30:23","date_gmt":"2024-06-29T08:30:23","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=389291"},"modified":"-0001-11-30T00:00:00","modified_gmt":"2024-06-29T08:30:23","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=389291","title":{"rendered":"<span>\u0423\u0441\u043a\u043e\u0440\u044f\u0435\u043c Python \u0432 \u0441\u0442\u043e \u0440\u0430\u0437 \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 \u043c\u0435\u043d\u0435\u0435 \u0447\u0435\u043c \u0441\u0442\u0430 \u0441\u0442\u0440\u043e\u043a \u043d\u0430 Rust<\/span>"},"content":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-1\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\"><a href=\"https:\/\/habr.com\/ru\/company\/ruvds\/blog\/732530\/\"><\/p>\n<div style=\"text-align:center;\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/webt\/ve\/wi\/bl\/vewibluh8e0erhybvpmggohupnw.jpeg\" data-src=\"https:\/\/habrastorage.org\/webt\/ve\/wi\/bl\/vewibluh8e0erhybvpmggohupnw.jpeg\" data-blurred=\"true\"\/><\/div>\n<p><\/a><br \/>  \u041e\u0434\u043d\u0430\u0436\u0434\u044b \u043d\u0430 \u0440\u0430\u0431\u043e\u0442\u0435 \u0443 \u043d\u0430\u0441 \u0432\u043e\u0437\u043d\u0438\u043a\u043b\u0430 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 \u0441 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c\u044e \u043e\u0434\u043d\u043e\u0439 \u0438\u0437 \u043d\u0430\u0448\u0438\u0445 \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0445 Python-\u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a.<\/p>\n<p>  \u042d\u0442\u0430 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0444\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u0442 \u0444\u0443\u043d\u0434\u0430\u043c\u0435\u043d\u0442 \u043d\u0430\u0448\u0435\u0433\u043e \u043a\u043e\u043d\u0432\u0435\u0439\u0435\u0440\u0430 3D-\u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438. \u042d\u0442\u043e \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0431\u043e\u043b\u044c\u0448\u0430\u044f \u0438 \u0441\u043b\u043e\u0436\u043d\u0430\u044f \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0449\u0430\u044f NumPy \u0438 \u0434\u0440\u0443\u0433\u0438\u0435 \u043d\u0430\u0443\u0447\u043d\u044b\u0435 \u043f\u0430\u043a\u0435\u0442\u044b Python \u0434\u043b\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0448\u0438\u0440\u043e\u043a\u043e\u0433\u043e \u0441\u043f\u0435\u043a\u0442\u0440\u0430 \u043c\u0430\u0442\u0435\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u0438 \u0433\u0435\u043e\u043c\u0435\u0442\u0440\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0439.<\/p>\n<p>  \u041a\u0440\u043e\u043c\u0435 \u0442\u043e\u0433\u043e, \u043d\u0430\u0448\u0430 \u0441\u0438\u0441\u0442\u0435\u043c\u0430 \u0434\u043e\u043b\u0436\u043d\u0430 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043d\u0430 \u043c\u043e\u0449\u043d\u043e\u0441\u0442\u044f\u0445 \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0438 \u0441 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043d\u044b\u043c\u0438 \u0440\u0435\u0441\u0443\u0440\u0441\u0430\u043c\u0438 CPU, \u0438 \u0445\u043e\u0442\u044f \u043f\u043e\u043d\u0430\u0447\u0430\u043b\u0443 \u043e\u043d\u0430 \u0441\u043f\u0440\u0430\u0432\u043b\u044f\u043b\u0430\u0441\u044c \u0445\u043e\u0440\u043e\u0448\u043e, \u0441 \u0440\u043e\u0441\u0442\u043e\u043c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u0444\u0438\u0437\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u0443 \u043d\u0430\u0441 \u043d\u0430\u0447\u0430\u043b\u0438 \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u0442\u044c \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b, \u0430 \u043d\u0430\u0448\u0430 \u0441\u0438\u0441\u0442\u0435\u043c\u0430 \u0435\u0434\u0432\u0430 \u0432\u044b\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u043b\u0430 \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0443.<\/p>\n<p>  \u041c\u044b \u043f\u0440\u0438\u0448\u043b\u0438 \u043a \u0432\u044b\u0432\u043e\u0434\u0443, \u0447\u0442\u043e \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0443\u0432\u0435\u043b\u0438\u0447\u0438\u0432\u0448\u0435\u0439\u0441\u044f \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u043e\u0439 \u043d\u0443\u0436\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0441\u0438\u0441\u0442\u0435\u043c\u0443, \u043f\u043e \u043a\u0440\u0430\u0439\u043d\u0435\u0439 \u043c\u0435\u0440\u0435, \u0432 \u043f\u044f\u0442\u044c\u0434\u0435\u0441\u044f\u0442 \u0440\u0430\u0437 \u0431\u044b\u0441\u0442\u0440\u0435\u0435, \u0438 \u0440\u0435\u0448\u0438\u043b\u0438, \u0447\u0442\u043e \u043f\u043e\u043c\u043e\u0447\u044c \u0432 \u044d\u0442\u043e\u043c \u043d\u0430\u043c \u043c\u043e\u0436\u0435\u0442 Rust.<\/p>\n<p>  \u0422\u0430\u043a \u043a\u0430\u043a \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438, \u0441 \u043a\u043e\u0442\u043e\u0440\u044b\u043c\u0438 \u043c\u044b \u0441\u0442\u043e\u043b\u043a\u043d\u0443\u043b\u0438\u0441\u044c, \u0432\u0441\u0442\u0440\u0435\u0447\u0430\u044e\u0442\u0441\u044f \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0447\u0430\u0441\u0442\u043e, \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0432\u043e\u0441\u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0438 \u0440\u0435\u0448\u0438\u0442\u044c \u0438\u0445 \u043f\u0440\u044f\u043c\u043e \u0437\u0434\u0435\u0441\u044c, \u0432 (\u043d\u0435 \u0442\u0430\u043a\u043e\u0439 \u0443\u0436 \u043a\u043e\u0440\u043e\u0442\u043a\u043e\u0439) \u0441\u0442\u0430\u0442\u044c\u0435.<\/p>\n<p>  \u0422\u0430\u043a \u0447\u0442\u043e \u0437\u0430\u0432\u0430\u0440\u0438\u0442\u0435 \u0441\u0435\u0431\u0435 \u0447\u0430\u044e (\u0438\u043b\u0438 \u043a\u043e\u0444\u0435) \u0438 \u044f \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443 \u0432\u0430\u043c (\u0430) \u043e \u0441\u0430\u043c\u043e\u0439 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0435 \u0438 (\u0431) \u043e \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u0438\u0442\u0435\u0440\u0430\u0446\u0438\u044f\u0445 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u044b \u0441\u043c\u043e\u0433\u043b\u0438 \u043f\u0440\u0438\u043c\u0435\u043d\u0438\u0442\u044c \u0434\u043b\u044f \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u044d\u0442\u043e\u0439 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b.<\/p>\n<p>  \u0415\u0441\u043b\u0438 \u0432\u044b \u0445\u043e\u0442\u0438\u0442\u0435 \u0441\u0440\u0430\u0437\u0443 \u043f\u0435\u0440\u0435\u0439\u0442\u0438 \u043a \u043f\u043e\u043b\u0443\u0447\u0438\u0432\u0448\u0435\u043c\u0443\u0441\u044f \u043a\u043e\u0434\u0443, \u0442\u043e \u0447\u0438\u0442\u0430\u0439\u0442\u0435 \u0440\u0430\u0437\u0434\u0435\u043b \u00ab\u041f\u043e\u0434\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u0438\u0442\u043e\u0433\u043e\u0432\u00bb.<br \/>  <a name=\"habracut\"><\/a>  <\/p>\n<h2><font color=\"#3AC1EF\">\u258d \u041d\u0430\u0448 \u043f\u0440\u0438\u043c\u0435\u0440<\/font><\/h2>\n<p>  \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u0443\u044e \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0431\u0443\u0434\u0435\u0442 \u0434\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043d\u0430\u0448\u0438 \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0435 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 (\u043e\u0434\u043d\u0430\u043a\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u044e\u0449\u0430\u044f \u0441\u043e\u0432\u0435\u0440\u0448\u0435\u043d\u043d\u043e \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u0443\u044e \u0440\u0430\u0431\u043e\u0442\u0443).<\/p>\n<p>  \u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u044c\u0442\u0435, \u0447\u0442\u043e \u0443 \u0432\u0430\u0441 \u0435\u0441\u0442\u044c \u0441\u043f\u0438\u0441\u043e\u043a \u043c\u043d\u043e\u0433\u043e\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a\u043e\u0432 \u0438 \u0441\u043f\u0438\u0441\u043e\u043a \u0442\u043e\u0447\u0435\u043a, \u0432\u0441\u0451 \u044d\u0442\u043e \u0432 2D. \u0414\u043b\u044f \u0431\u0438\u0437\u043d\u0435\u0441-\u043b\u043e\u0433\u0438\u043a\u0438 \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u00ab\u0441\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c\u00bb \u043a\u0430\u0436\u0434\u0443\u044e \u0442\u043e\u0447\u043a\u0443 \u0441 \u043e\u0434\u043d\u0438\u043c \u043c\u043d\u043e\u0433\u043e\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a\u043e\u043c.<\/p>\n<p>  \u041d\u0430\u0448\u0430 \u0432\u044b\u043c\u044b\u0448\u043b\u0435\u043d\u043d\u0430\u044f \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0431\u0443\u0434\u0435\u0442:<\/p>\n<ol>\n<li>\u041d\u0430\u0447\u0438\u043d\u0430\u0442\u044c \u0441 \u0438\u0441\u0445\u043e\u0434\u043d\u043e\u0433\u043e \u0441\u043f\u0438\u0441\u043a\u0430 \u0442\u043e\u0447\u0435\u043a \u0438 \u043c\u043d\u043e\u0433\u043e\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a\u043e\u0432 (\u0432 2D).<\/li>\n<li>\u0414\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0439 \u0442\u043e\u0447\u043a\u0438 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0430\u043d\u0438\u0438 \u0440\u0430\u0441\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u0434\u043e \u0446\u0435\u043d\u0442\u0440\u0430 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u044c \u0433\u043e\u0440\u0430\u0437\u0434\u043e \u043c\u0435\u043d\u044c\u0448\u0435\u0435 \u043f\u043e\u0434\u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e \u043c\u043d\u043e\u0433\u043e\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a\u043e\u0432, \u0431\u043b\u0438\u0436\u0430\u0439\u0448\u0438\u0445 \u043a \u043d\u0435\u0439.<\/li>\n<li>\u0418\u0437 \u044d\u0442\u0438\u0445 \u043c\u043d\u043e\u0433\u043e\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a\u043e\u0432 \u0432\u044b\u0431\u0438\u0440\u0430\u0442\u044c \u00ab\u043b\u0443\u0447\u0448\u0438\u0439\u00bb (\u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044f \u00ab\u043b\u0443\u0447\u0448\u0435\u0433\u043e\u00bb \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u00ab\u0441 \u043d\u0430\u0438\u043c\u0435\u043d\u044c\u0448\u0435\u0439 \u043f\u043b\u043e\u0449\u0430\u0434\u044c\u044e\u00bb).<\/li>\n<\/ol>\n<p>  \u0412 \u043a\u043e\u0434\u0435 \u044d\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u0442\u0430\u043a (\u043f\u043e\u043b\u043d\u044b\u0439 \u043a\u043e\u0434 \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0439\u0442\u0438 <a href=\"https:\/\/github.com\/ohadravid\/poly-match\">\u0437\u0434\u0435\u0441\u044c<\/a>):<\/p>\n<pre><code class=\"python\">from typing import List, Tuple import numpy as np from dataclasses import dataclass from functools import cached_property  Point = np.array  @dataclass class Polygon:     x: np.array     y: np.array      @cached_property     def center(self) -> Point: ...     def area(self) -> float: ...  def find_close_polygons(polygon_subset: List[Polygon], point: Point, max_dist: float) -> List[Polygon]:     ...  def select_best_polygon(polygon_sets: List[Tuple[Point, List[Polygon]]]) -> List[Tuple[Point, Polygon]]:     ...  def main(polygons: List[Polygon], points: np.ndarray) -> List[Tuple[Point, Polygon]]:     ...<\/code><\/pre>\n<p>  <b><font color=\"#3AC1EF\">\u041e\u0441\u043d\u043e\u0432\u043d\u0430\u044f \u0441\u043b\u043e\u0436\u043d\u043e\u0441\u0442\u044c (\u0441 \u0442\u043e\u0447\u043a\u0438 \u0437\u0440\u0435\u043d\u0438\u044f \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438) \u0437\u0430\u043a\u043b\u044e\u0447\u0430\u0435\u0442\u0441\u044f \u0432 \u0441\u043c\u0435\u0448\u0435\u043d\u0438\u0438 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 Python \u0438 \u043c\u0430\u0441\u0441\u0438\u0432\u043e\u0432 numpy.<\/font><\/b><\/p>\n<p>  \u0421\u043a\u043e\u0440\u043e \u043c\u044b \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e \u044d\u0442\u043e \u043f\u0440\u043e\u0430\u043d\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u043c.<\/p>\n<p>  \u0421\u0442\u043e\u0438\u0442 \u0437\u0430\u043c\u0435\u0442\u0438\u0442\u044c, \u0447\u0442\u043e \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0438\u0441\u043a\u0443\u0441\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0433\u043e \u043f\u0440\u0438\u043c\u0435\u0440\u0430 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u0442\u044c \u0447\u0430\u0441\u0442\u0438\/\u0432\u0441\u0451 \u0446\u0435\u043b\u0438\u043a\u043e\u043c \u0432 <a href=\"https:\/\/numpy.org\/doc\/stable\/glossary.html#term-vectorization\">\u0432\u0435\u043a\u0442\u043e\u0440\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439<\/a> numpy, \u043d\u043e \u044d\u0442\u043e \u043f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0434\u043b\u044f \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0439 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u0438 \u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u0434\u0435\u043b\u0430\u0435\u0442 \u043a\u043e\u0434 \u0433\u043e\u0440\u0430\u0437\u0434\u043e \u043c\u0435\u043d\u0435\u0435 \u0447\u0438\u0442\u0430\u0435\u043c\u044b\u043c \u0438 \u043c\u043e\u0434\u0438\u0444\u0438\u0446\u0438\u0440\u0443\u0435\u043c\u044b\u043c, \u0430 \u043f\u0440\u0435\u0438\u043c\u0443\u0449\u0435\u0441\u0442\u0432\u0430 \u043e\u043a\u0430\u0436\u0443\u0442\u0441\u044f \u043d\u0435\u0437\u043d\u0430\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u043c\u0438 (<a href=\"https:\/\/github.com\/ohadravid\/poly-match\/blob\/main\/poly_match_v1_5_vectorized.py\">\u0437\u0434\u0435\u0441\u044c<\/a> \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0447\u0430\u0441\u0442\u0438\u0447\u043d\u043e \u0432\u0435\u043a\u0442\u043e\u0440\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u0430\u044f \u0432\u0435\u0440\u0441\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0431\u044b\u0441\u0442\u0440\u0435\u0435, \u043d\u043e \u0434\u0430\u043b\u0435\u043a\u0430 \u043e\u0442 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u044b \u0434\u043e\u0441\u0442\u0438\u0433\u043d\u0435\u043c).<\/p>\n<p>  \u041a\u0440\u043e\u043c\u0435 \u0442\u043e\u0433\u043e, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u043b\u044e\u0431\u044b\u0445 \u0442\u0440\u044e\u043a\u043e\u0432 \u0441 JIT (PyPy \/ numba) \u043f\u0440\u0438\u0432\u043e\u0434\u0438\u0442 \u043a \u043e\u0447\u0435\u043d\u044c \u043c\u0430\u043b\u0435\u043d\u044c\u043a\u043e\u0439 \u0432\u044b\u0433\u043e\u0434\u0435 (\u0447\u0442\u043e\u0431\u044b \u0443\u0431\u0435\u0434\u0438\u0442\u044c\u0441\u044f, \u043c\u044b \u0438\u0437\u043c\u0435\u0440\u0438\u043c \u044d\u0442\u043e).<\/p>\n<h2><font color=\"#3AC1EF\">\u258d \u041f\u043e\u0447\u0435\u043c\u0443 \u0431\u044b \u043f\u0440\u043e\u0441\u0442\u043e \u043d\u0435 \u041f\u0435\u0440\u0435\u043f\u0438\u0441\u0430\u0442\u044c \u0412\u0441\u0451 \u041d\u0430 Rust\u2122?<\/font><\/h2>\n<p>  \u041a\u0430\u043a \u043d\u0438 \u043f\u0440\u0438\u0432\u043b\u0435\u043a\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0431\u044b\u043b\u043e \u043f\u043e\u043b\u043d\u043e\u0435 \u043f\u0435\u0440\u0435\u043f\u0438\u0441\u044b\u0432\u0430\u043d\u0438\u0435, \u043e\u043d\u043e \u0438\u043c\u0435\u043b\u043e \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043f\u0440\u043e\u0431\u043b\u0435\u043c:<\/p>\n<ol>\n<li>\u0411\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0443\u0436\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0430 numpy \u0434\u043b\u044f \u043c\u043d\u043e\u0433\u0438\u0445 \u0441\u0432\u043e\u0438\u0445 \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0439, \u0442\u0430\u043a \u043f\u043e\u0447\u0435\u043c\u0443 \u043c\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u043e\u0436\u0438\u0434\u0430\u0442\u044c, \u0447\u0442\u043e Rust \u0431\u0443\u0434\u0435\u0442 \u043b\u0443\u0447\u0448\u0435?<\/li>\n<li>\u041e\u043d\u0430 \u0431\u043e\u043b\u044c\u0448\u0430\u044f, \u0441\u043b\u043e\u0436\u043d\u0430\u044f, \u043e\u0447\u0435\u043d\u044c \u0432\u0430\u0436\u043d\u0430\u044f \u0434\u043b\u044f \u0431\u0438\u0437\u043d\u0435\u0441\u0430 \u0438 \u0432\u044b\u0441\u043e\u043a\u043e\u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u0438\u0447\u0435\u0441\u043a\u0430\u044f, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u044d\u0442\u043e \u0437\u0430\u0439\u043c\u0451\u0442 \u043c\u0435\u0441\u044f\u0446\u044b \u0440\u0430\u0431\u043e\u0442\u044b, \u0430 \u0431\u0435\u0434\u043d\u044b\u0439 \u0441\u0435\u0440\u0432\u0435\u0440 \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0438 \u043f\u043e\u043c\u0438\u0440\u0430\u0435\u0442 \u0443\u0436\u0435 <strong>\u0441\u0435\u0439\u0447\u0430\u0441<\/strong>.<\/li>\n<li>\u0413\u0440\u0443\u043f\u043f\u0430 \u0434\u0440\u0443\u0436\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0445 \u0438\u0441\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u0430\u043a\u0442\u0438\u0432\u043d\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u043b\u0430 \u043d\u0430\u0434 \u044d\u0442\u043e\u0439 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u043e\u0439, \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u044f \u0443\u043b\u0443\u0447\u0448\u0435\u043d\u043d\u044b\u0435 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u044b \u0438 \u043f\u0440\u043e\u0432\u043e\u0434\u044f \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e \u044d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u043e\u0432. \u0418\u0445 \u043d\u0435 \u043e\u0447\u0435\u043d\u044c \u043f\u043e\u0440\u0430\u0434\u0443\u0435\u0442 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u044c \u0438\u0437\u0443\u0447\u0435\u043d\u0438\u044f \u043d\u043e\u0432\u043e\u0433\u043e \u044f\u0437\u044b\u043a\u0430 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f, \u043e\u0436\u0438\u0434\u0430\u043d\u0438\u044f \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u0438 \u0438 \u0431\u043e\u0440\u044c\u0431\u044b \u0441 borrow checker. \u041e\u043d\u0438 \u0431\u0443\u0434\u0443\u0442 \u043f\u0440\u0438\u0437\u043d\u0430\u0442\u0435\u043b\u044c\u043d\u044b, \u0435\u0441\u043b\u0438 \u043c\u044b \u043d\u0435 \u0441\u0442\u0430\u043d\u0435\u043c \u0442\u0430\u043a \u0443\u0441\u043b\u043e\u0436\u043d\u044f\u0442\u044c \u0438\u0445 \u0440\u0430\u0431\u043e\u0442\u0443.<\/li>\n<\/ol>\n<p>  <\/p>\n<h2><font color=\"#3AC1EF\">\u258d \u042d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u0438\u0440\u0443\u0435\u043c<\/font><\/h2>\n<p>  \u041d\u0430\u0441\u0442\u0430\u043b\u043e \u0432\u0440\u0435\u043c\u044f \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043d\u0430\u0448\u0435\u0433\u043e \u0434\u0440\u0443\u0433\u0430 \u2014 \u043f\u0440\u043e\u0444\u0438\u043b\u0438\u0440\u043e\u0432\u0449\u0438\u043a.<\/p>\n<p>  Python \u0438\u043c\u0435\u0435\u0442 \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0439 \u043f\u0440\u043e\u0444\u0438\u043b\u0438\u0440\u043e\u0432\u0449\u0438\u043a (<code>cProfile<\/code>), \u043d\u043e \u0432 \u0434\u0430\u043d\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u044d\u0442\u043e \u043d\u0435\u043f\u043e\u0434\u0445\u043e\u0434\u044f\u0449\u0438\u0439 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b:<\/p>\n<ol>\n<li>\u041e\u043d \u043d\u0430\u0432\u0435\u0441\u0438\u0442 \u0431\u043e\u043b\u044c\u0448\u0443\u044e \u0442\u0440\u0430\u0442\u0443 \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432 \u043d\u0430 \u0432\u0435\u0441\u044c \u043a\u043e\u0434 \u043d\u0430 Python, \u043d\u043e \u043d\u0435 \u0443\u0432\u0435\u043b\u0438\u0447\u0438\u0442 \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0443 \u043d\u0430 \u043d\u0430\u0442\u0438\u0432\u043d\u044b\u0439 \u043a\u043e\u0434, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u043c\u043e\u0433\u0443\u0442 \u043e\u043a\u0430\u0437\u0430\u0442\u044c\u0441\u044f \u0438\u0441\u043a\u0430\u0436\u0451\u043d\u043d\u044b\u043c\u0438.<\/li>\n<li>\u041c\u044b \u043d\u0435 \u0441\u043c\u043e\u0436\u0435\u043c \u043f\u0440\u043e\u0441\u043c\u0430\u0442\u0440\u0438\u0432\u0430\u0442\u044c \u043d\u0430\u0442\u0438\u0432\u043d\u044b\u0435 \u043a\u0430\u0434\u0440\u044b, \u0442\u043e \u0435\u0441\u0442\u044c \u043d\u0435 \u0441\u043c\u043e\u0436\u0435\u043c \u0437\u0430\u0433\u043b\u044f\u043d\u0443\u0442\u044c \u0432 \u043d\u0430\u0448 \u043a\u043e\u0434 \u043d\u0430 Rust.<\/li>\n<\/ol>\n<p>  \u041c\u044b \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <code>py-spy<\/code> (<a href=\"https:\/\/github.com\/benfred\/py-spy\">GitHub<\/a>).<\/p>\n<p>  <code>py-spy<\/code> \u2014 \u044d\u0442\u043e <a href=\"https:\/\/en.wikipedia.org\/wiki\/Profiling_(computer_programming)#Statistical_profilers\">\u0441\u044d\u043c\u043f\u043b\u0438\u0440\u0443\u044e\u0449\u0438\u0439 \u043f\u0440\u043e\u0444\u0438\u043b\u0438\u0440\u043e\u0432\u0449\u0438\u043a<\/a>, \u0441\u043f\u043e\u0441\u043e\u0431\u043d\u044b\u0439 \u0437\u0430\u0433\u043b\u044f\u0434\u044b\u0432\u0430\u0442\u044c \u0432 \u043d\u0430\u0442\u0438\u0432\u043d\u044b\u0435 \u043a\u0430\u0434\u0440\u044b.<\/p>\n<p>  \u0420\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0438 \u0442\u0430\u043a\u0436\u0435 \u043b\u044e\u0431\u0435\u0437\u043d\u043e \u043e\u043f\u0443\u0431\u043b\u0438\u043a\u043e\u0432\u0430\u043b\u0438 \u0433\u043e\u0442\u043e\u0432\u044b\u0435 wheel \u0434\u043b\u044f pypi, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u043e \u0432\u0432\u0435\u0441\u0442\u0438 <code>pip install py-spy<\/code> \u0438 \u043f\u0440\u0438\u0441\u0442\u0443\u043f\u0430\u0442\u044c \u043a \u0440\u0430\u0431\u043e\u0442\u0435.<\/p>\n<p>  \u0415\u0449\u0451 \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0447\u0442\u043e-\u0442\u043e \u0434\u043b\u044f \u0438\u0437\u043c\u0435\u0440\u0435\u043d\u0438\u0439.<\/p>\n<pre><code class=\"python\"># measure.py import time import poly_match import os   # \u0421\u043d\u0438\u0436\u0430\u0435\u043c \u0448\u0443\u043c, \u0432 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043f\u043e\u0432\u044b\u0448\u0430\u044f \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c. os.environ[\"OPENBLAS_NUM_THREADS\"] = \"1\"  polygons, points = poly_match.generate_example()  # \u041c\u044b \u0431\u0443\u0434\u0435\u043c \u0443\u0432\u0435\u043b\u0438\u0447\u0438\u0432\u0430\u0442\u044c \u044d\u0442\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435, \u043a\u043e\u0433\u0434\u0430 \u043d\u0430\u0448 \u043a\u043e\u0434 \u0431\u0443\u0434\u0435\u0442 \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c\u0441\u044f \u0432\u0441\u0451 \u0431\u044b\u0441\u0442\u0440\u0435\u0435 \u0438 \u0431\u044b\u0441\u0442\u0440\u0435\u0435. NUM_ITER = 10  t0 = time.perf_counter() for _ in range(NUM_ITER):     poly_match.main(polygons, points) t1 = time.perf_counter()  took = (t1 - t0) \/ NUM_ITER print(f\"Took and avg of {took * 1000:.2f}ms per iteration\")<\/code><\/pre>\n<p>  \u0412\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u043d\u0435 \u043e\u0447\u0435\u043d\u044c \u043d\u0430\u0443\u0447\u043d\u043e, \u043d\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u0442 \u043d\u0430\u043c \u0441\u0434\u0435\u043b\u0430\u0442\u044c <em>\u043e\u0433\u0440\u043e\u043c\u043d\u044b\u0439<\/em> \u0448\u0430\u0433 \u0432\u043f\u0435\u0440\u0451\u0434.<\/p>\n<blockquote><p>\u00ab\u0425\u043e\u0440\u043e\u0448\u0438\u0439 \u0431\u0435\u043d\u0447\u043c\u0430\u0440\u043a\u0438\u043d\u0433 \u2014 \u044d\u0442\u043e \u0441\u043b\u043e\u0436\u043d\u043e. \u0422\u0435\u043c \u043d\u0435 \u043c\u0435\u043d\u0435\u0435 \u2014 \u043d\u0435 \u0441\u043b\u0438\u0448\u043a\u043e\u043c \u043d\u0430\u043b\u0435\u0433\u0430\u0439\u0442\u0435 \u043d\u0430 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0438\u0434\u0435\u0430\u043b\u044c\u043d\u043e\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u0431\u0435\u043d\u0447\u043c\u0430\u0440\u043a\u0438\u043d\u0433\u0430, \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u043a\u043e\u0433\u0434\u0430 \u0432\u044b \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442\u0435 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0443\u00bb. ~ \u041d\u0438\u043a\u043e\u043b\u0430\u0441 \u041d\u0435\u0442\u0435\u0440\u043a\u043e\u0442, <a href=\"https:\/\/nnethercote.github.io\/perf-book\/benchmarking.html\">\u00abThe Rust Performance Book\u00bb<\/a><\/p><\/blockquote>\n<p>  \u041f\u043e\u0441\u043b\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u044d\u0442\u043e\u0433\u043e \u0441\u043a\u0440\u0438\u043f\u0442\u0430 \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u043c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b, \u043e\u0442 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043c\u043e\u0436\u043d\u043e \u043e\u0442\u0442\u0430\u043b\u043a\u0438\u0432\u0430\u0442\u044c\u0441\u044f:<\/p>\n<pre><code class=\"bash\">$ python measure.py Took an avg of 293.41ms per iteration<\/code><\/pre>\n<p>  \u0414\u043b\u044f \u043d\u0430\u0448\u0435\u0439 \u043d\u0430\u0441\u0442\u043e\u044f\u0449\u0435\u0439 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0438 50 \u0440\u0430\u0437\u043d\u044b\u0445 \u0441\u043b\u0443\u0447\u0430\u0435\u0432, \u0447\u0442\u043e\u0431\u044b \u0433\u0430\u0440\u0430\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u043e\u043a\u0440\u044b\u0442\u0438\u0435 \u0432\u0441\u0435\u0445 \u0441\u043b\u0443\u0447\u0430\u0435\u0432.<\/p>\n<p>  \u042d\u0442\u043e \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u043e\u0432\u0430\u043b\u043e \u043e\u0431\u0449\u0435\u0439 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u0441\u0438\u0441\u0442\u0435\u043c\u044b, \u0442\u043e \u0435\u0441\u0442\u044c \u043c\u044b \u043c\u043e\u0433\u043b\u0438 \u043f\u0440\u0438\u0441\u0442\u0443\u043f\u0430\u0442\u044c \u043a \u0431\u043e\u0440\u044c\u0431\u0435 \u0441 \u044d\u0442\u0438\u043c\u0438 \u0447\u0438\u0441\u043b\u0430\u043c\u0438.<\/p>\n<p>  \u041f\u0440\u0438\u043c\u0435\u0447\u0430\u043d\u0438\u0435: \u043c\u043e\u0436\u043d\u043e \u0442\u0430\u043a\u0436\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u0438\u0437\u043c\u0435\u0440\u0435\u043d\u0438\u044f \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 PyPy (\u0442\u0430\u043a\u0436\u0435 \u043c\u044b \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0440\u0430\u0437\u043e\u0433\u0440\u0435\u0432, \u0447\u0442\u043e\u0431\u044b JIT \u043f\u043e\u043a\u0430\u0437\u0430\u043b\u0430 \u0441\u0432\u043e\u044e \u043c\u0430\u0433\u0438\u044e).<\/p>\n<pre><code class=\"bash\">$ conda create -n pypyenv -c conda-forge pypy numpy &amp;&amp; conda activate pypyenv $ pypy measure_with_warmup.py Took an avg of 1495.81ms per iteration<\/code><\/pre>\n<p>  <\/p>\n<h2><font color=\"#3AC1EF\">\u258d \u0418\u0437\u043c\u0435\u0440\u0435\u043d\u0438\u044f \u2014 \u044d\u0442\u043e \u0433\u043b\u0430\u0432\u043d\u043e\u0435<\/font><\/h2>\n<p>  \u0422\u0430\u043a, \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0432\u044b\u044f\u0441\u043d\u0438\u043c, \u0447\u0442\u043e \u0436\u0435 \u0442\u0443\u0442 \u0442\u0430\u043a \u043c\u0435\u0434\u043b\u0435\u043d\u043d\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442.<\/p>\n<pre><code class=\"bash\">$ py-spy record --native -o profile.svg -- python measure.py py-spy> Sampling process 100 times a second. Press Control-C to exit.  Took an avg of 365.43ms per iteration  py-spy> Stopped sampling because process exited py-spy> Wrote flamegraph data to 'profile.svg'. Samples: 391 Errors: 0<\/code><\/pre>\n<p>  \u041c\u044b \u0443\u0436\u0435 \u0432\u0438\u0434\u0438\u043c, \u0447\u0442\u043e \u043b\u0438\u0448\u043d\u044f\u044f \u0442\u0440\u0430\u0442\u0430 \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432 \u0442\u0443\u0442 \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u043c\u0430\u043b\u0430. \u041f\u0440\u043e\u0441\u0442\u043e \u0434\u043b\u044f \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044f, \u043f\u0440\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 <code>cProfile<\/code> \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0435:<\/p>\n<pre><code class=\"bash\">$ python -m cProfile measure.py Took an avg of 546.47ms per iteration          7551778 function calls (7409483 primitive calls) in 7.806 seconds          ...<\/code><\/pre>\n<p>  \u041c\u044b \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0432\u043e\u0442 \u0442\u0430\u043a\u043e\u0439 \u043a\u0440\u0430\u0441\u0438\u0432\u044b\u0439 \u043a\u0440\u0430\u0441\u043d\u044b\u0439 \u0433\u0440\u0430\u0444\u0438\u043a, \u043d\u0430\u0437\u044b\u0432\u0430\u0435\u043c\u044b\u0439 <a href=\"https:\/\/www.brendangregg.com\/FlameGraphs\/cpuflamegraphs.html\">flamegraph<\/a>:<\/p>\n<div style=\"text-align:center;\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/u4\/3m\/oz\/u43mozwgcnf8hw5_rj5hducg1a0.png\" data-src=\"https:\/\/habrastorage.org\/webt\/u4\/3m\/oz\/u43mozwgcnf8hw5_rj5hducg1a0.png\"\/><\/div>\n<p>  \u041a\u0430\u0436\u0434\u044b\u0439 \u043f\u0440\u044f\u043c\u043e\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a \u2014 \u044d\u0442\u043e \u0444\u0443\u043d\u043a\u0446\u0438\u044f. \u0412 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b\u0435 \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/ohadravid.github.io\/posts\/2023-03-rusty-python\/#measure-first\">\u0433\u0440\u0430\u0444\u0438\u043a \u0438\u043d\u0442\u0435\u0440\u0430\u043a\u0442\u0438\u0432\u0435\u043d<\/a> \u0438 \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0432\u0438\u0434\u0435\u0442\u044c \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0435 \u0432\u0440\u0435\u043c\u044f, \u043f\u0440\u043e\u0432\u043e\u0434\u0438\u043c\u043e\u0435 \u0432 \u043a\u0430\u0436\u0434\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u0432 \u0442\u043e\u043c \u0447\u0438\u0441\u043b\u0435 \u0432 \u0444\u0443\u043d\u043a\u0446\u0438\u044f\u0445, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043e\u043d\u0430 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442 (\u0441\u043f\u0443\u0441\u043a\u0430\u044f\u0441\u044c \u0432\u043d\u0438\u0437 \u043f\u043e \u0433\u0440\u0430\u0444\u0438\u043a\u0443\/\u0441\u0442\u0435\u043a\u0443). \u041f\u043e\u043f\u0440\u043e\u0431\u0443\u0439\u0442\u0435 \u043d\u0430\u0436\u0430\u0442\u044c \u043d\u0430 \u043f\u0440\u044f\u043c\u043e\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a <code>norm<\/code>, \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u0438\u0431\u043b\u0438\u0437\u0438\u0442\u044c \u0435\u0433\u043e.<\/p>\n<p>  \u0417\u0434\u0435\u0441\u044c \u043c\u043e\u0436\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 \u0432\u044b\u0432\u043e\u0434\u044b:<\/p>\n<ol>\n<li>\u041f\u043e\u0434\u0430\u0432\u043b\u044f\u044e\u0449\u0435\u0435 \u0431\u043e\u043b\u044c\u0448\u0438\u043d\u0441\u0442\u0432\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0442\u0440\u0430\u0442\u0438\u0442\u0441\u044f \u0432 <code>find_close_polygons<\/code>.<\/li>\n<li>\u041e\u0441\u043d\u043e\u0432\u043d\u0430\u044f \u0447\u0430\u0441\u0442\u044c \u044d\u0442\u043e\u0433\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0442\u0440\u0430\u0442\u0438\u0442\u0441\u044f \u043d\u0430 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 <code>norm<\/code>, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u0435\u0439 numpy.<\/li>\n<\/ol>\n<p>  \u0418\u0442\u0430\u043a, \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0432\u0437\u0433\u043b\u044f\u043d\u0435\u043c \u043d\u0430 <code>find_close_polygons<\/code>:<\/p>\n<pre><code class=\"python\">def find_close_polygons(     polygon_subset: List[Polygon], point: np.array, max_dist: float ) -> List[Polygon]:     close_polygons = []     for poly in polygon_subset:         if np.linalg.norm(poly.center - point) &lt; max_dist:             close_polygons.append(poly)      return close_polygons<\/code><\/pre>\n<p>  \u041c\u044b \u043f\u0435\u0440\u0435\u043f\u0438\u0448\u0435\u043c \u044d\u0442\u0443 \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u043d\u0430 Rust.<\/p>\n<p>  \u041f\u0440\u0435\u0436\u0434\u0435 \u0447\u0435\u043c \u0432\u0434\u0430\u0432\u0430\u0442\u044c\u0441\u044f \u0432 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0441\u0442\u0438, \u0432\u0430\u0436\u043d\u043e \u0437\u0430\u043c\u0435\u0442\u0438\u0442\u044c \u0437\u0434\u0435\u0441\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043c\u043e\u043c\u0435\u043d\u0442\u043e\u0432:<\/p>\n<ol>\n<li>\u042d\u0442\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0441\u043b\u043e\u0436\u043d\u044b\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u044b (<code>Polygon<\/code>, <code>np.array<\/code>).<\/li>\n<li>\u0420\u0430\u0437\u043c\u0435\u0440 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 \u043d\u0435\u0442\u0440\u0438\u0432\u0438\u0430\u043b\u0435\u043d (\u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0437\u0430\u0442\u0440\u0430\u0442\u043d\u044b\u043c).<\/li>\n<li>\u042d\u0442\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0447\u0430\u0441\u0442\u043e (\u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0432\u043d\u0435\u0441\u0451\u043d\u043d\u0430\u044f \u043d\u0430\u043c\u0438 \u043b\u0438\u0448\u043d\u044f\u044f \u0442\u0440\u0430\u0442\u0430 \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432, \u0432\u0435\u0440\u043e\u044f\u0442\u043d\u043e, \u0431\u0443\u0434\u0435\u0442 \u0438\u043c\u0435\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435).<\/li>\n<\/ol>\n<p>  <\/p>\n<h2><font color=\"#3AC1EF\">\u258d \u041c\u043e\u0439 \u043f\u0435\u0440\u0432\u044b\u0439 \u043c\u043e\u0434\u0443\u043b\u044c Rust<\/font><\/h2>\n<p>  <code>pyo3<\/code> \u2014 \u044d\u0442\u043e \u043a\u0440\u0435\u0439\u0442 \u0434\u043b\u044f \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u043c\u0435\u0436\u0434\u0443 Python \u0438 Rust. \u041e\u043d \u0438\u043c\u0435\u0435\u0442 \u0447\u0440\u0435\u0437\u0432\u044b\u0447\u0430\u0439\u043d\u043e \u0445\u043e\u0440\u043e\u0448\u0443\u044e \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044e, \u0430 \u0431\u0430\u0437\u043e\u0432\u0430\u044f \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u043e\u0431\u044a\u044f\u0441\u043d\u0435\u043d\u0430 <a href=\"https:\/\/pyo3.rs\/v0.18.1\/#using-rust-from-python\">\u0437\u0434\u0435\u0441\u044c<\/a>.<\/p>\n<p>  \u041c\u044b \u043d\u0430\u0437\u043e\u0432\u0451\u043c \u0441\u0432\u043e\u0439 \u043a\u0440\u0435\u0439\u0442 <code>poly_match_rs<\/code> \u0438 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u044e <code>find_close_polygons<\/code>.<\/p>\n<pre><code class=\"bash\">mkdir poly_match_rs &amp;&amp; cd \"$_\" pip install maturin maturin init --bindings pyo3 maturin develop<\/code><\/pre>\n<p>  \u0418\u0437\u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e \u043d\u0430\u0448 \u043a\u0440\u0435\u0439\u0442 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u0442\u0430\u043a:<\/p>\n<pre><code class=\"rust\">use pyo3::prelude::*;  #[pyfunction] fn find_close_polygons() -> PyResult&lt;()> {     Ok(()) }  #[pymodule] fn poly_match_rs(_py: Python, m: &amp;PyModule) -> PyResult&lt;()> {     m.add_function(wrap_pyfunction!(find_close_polygons, m)?)?;     Ok(()) }<\/code><\/pre>\n<p>  \u041d\u0430\u043c \u0442\u0430\u043a\u0436\u0435 \u043d\u0443\u0436\u043d\u043e \u043d\u0435 \u0437\u0430\u0431\u044b\u0432\u0430\u0442\u044c \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c <code>maturin develop<\/code> \u043a\u0430\u0436\u0434\u044b\u0439 \u0440\u0430\u0437, \u043a\u043e\u0433\u0434\u0430 \u043c\u044b \u043c\u0435\u043d\u044f\u0435\u043c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 Rust.<\/p>\n<p>  \u0412\u043e\u0442 \u0438 \u0432\u0441\u0451! \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0432\u044b\u0437\u043e\u0432\u0435\u043c \u043d\u0430\u0448\u0443 \u043d\u043e\u0432\u0443\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u0438 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c, \u0447\u0442\u043e \u043f\u0440\u043e\u0438\u0437\u043e\u0439\u0434\u0451\u0442.<\/p>\n<pre><code class=\"python\">>>> poly_match_rs.find_close_polygons(polygons, point, max_dist) E TypeError: poly_match_rs.poly_match_rs.find_close_polygons() takes no arguments (3 given)<\/code><\/pre>\n<p>  <\/p>\n<h2><font color=\"#3AC1EF\">\u258d v1 \u2014 \u043d\u0430\u0438\u0432\u043d\u0430\u044f \u0442\u0440\u0430\u043d\u0441\u043b\u044f\u0446\u0438\u044f Rust<\/font><\/h2>\n<p>  \u041d\u0430\u0447\u043d\u0451\u043c \u043c\u044b \u0441 \u0441\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043e\u0436\u0438\u0434\u0430\u0435\u043c\u043e\u0433\u043e API.<\/p>\n<p>  PyO3 \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0441\u043e\u043e\u0431\u0440\u0430\u0437\u0438\u0442\u0435\u043b\u0435\u043d \u043f\u0440\u0438 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u044f\u0445 \u0438\u0437 Python \u0432 Rust, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u044d\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u043e:<\/p>\n<pre><code class=\"rust\">#[pyfunction] fn find_close_polygons(polygons: Vec&lt;PyObject>, point: PyObject, max_dist: f64) -> PyResult&lt;Vec&lt;PyObject>> {     Ok(vec![]) }<\/code><\/pre>\n<p>  <code>PyObject<\/code> \u2014 \u044d\u0442\u043e (\u043a\u0430\u043a \u043f\u043e\u043d\u044f\u0442\u043d\u043e \u0438\u0437 \u0438\u043c\u0435\u043d\u0438) \u043e\u0431\u043e\u0431\u0449\u0451\u043d\u043d\u044b\u0439 \u043e\u0431\u044a\u0435\u043a\u0442 Python. \u041c\u044b \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u043f\u043e\u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c \u0441 \u043d\u0438\u043c.<\/p>\n<p>  \u042d\u0442\u043e \u0434\u043e\u043b\u0436\u043d\u043e \u0437\u0430\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0443 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c\u0441\u044f (\u0445\u043e\u0442\u044c \u0438 \u043d\u0435\u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e).<\/p>\n<p>  \u042f \u043f\u0440\u043e\u0441\u0442\u043e \u0441\u043a\u043e\u043f\u0438\u0440\u0443\u044e \u0438 \u0432\u0441\u0442\u0430\u0432\u043b\u044e \u0438\u0441\u0445\u043e\u0434\u043d\u0443\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u043d\u0430 Python, \u0430 \u043f\u043e\u0442\u043e\u043c \u0438\u0441\u043f\u0440\u0430\u0432\u043b\u044e \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0441.<\/p>\n<pre><code class=\"rust\">#[pyfunction] fn find_close_polygons(polygons: Vec&lt;PyObject>, point: PyObject, max_dist: f64) -> PyResult&lt;Vec&lt;PyObject>> {     let mut close_polygons = vec![];          for poly in polygons {         if norm(poly.center - point) &lt; max_dist {             close_polygons.push(poly)         }     }          Ok(close_polygons) }<\/code><\/pre>\n<p>  \u0417\u0434\u043e\u0440\u043e\u0432\u043e, \u043d\u043e \u044d\u0442\u043e \u043d\u0435 \u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u0443\u0435\u0442\u0441\u044f:<\/p>\n<pre><code class=\"plaintext\">% maturin develop ...  error[E0609]: no field `center` on type `Py&lt;PyAny>`  --> src\/lib.rs:8:22   | 8 |         if norm(poly.center - point) &lt; max_dist {   |                      ^^^^^^ unknown field   error[E0425]: cannot find function `norm` in this scope  --> src\/lib.rs:8:12   | 8 |         if norm(poly.center - point) &lt; max_dist {   |            ^^^^ not found in this scope   error: aborting due to 2 previous errors ] 58\/59: poly_match_rs<\/code><\/pre>\n<p>  \u0414\u043b\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u044d\u0442\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u043d\u0430\u043c \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u044e\u0442\u0441\u044f \u0442\u0440\u0438 \u043a\u0440\u0435\u0439\u0442\u0430:<\/p>\n<pre><code class=\"python\"># \u0414\u043b\u044f \u043d\u0430\u0442\u0438\u0432\u043d\u044b\u0445 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0439 \u0441 \u043c\u0430\u0441\u0441\u0438\u0432\u0430\u043c\u0438 Rust. ndarray = \"0.15\"  # \u0414\u043b\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \"norm\" \u0434\u043b\u044f \u043c\u0430\u0441\u0441\u0438\u0432\u043e\u0432. ndarray-linalg = \"0.16\"    # \u0414\u043b\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u044b\u043c numpy \u043e\u0431\u044a\u0435\u043a\u0442\u0430\u043c, \u043e\u0441\u043d\u043e\u0432\u0430\u043d\u043d\u044b\u043c \u043d\u0430 \"ndarray\". numpy = \"0.18\"<\/code><\/pre>\n<p>  \u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u0440\u0435\u0432\u0440\u0430\u0442\u0438\u043c \u043d\u0435\u043f\u0440\u043e\u0437\u0440\u0430\u0447\u043d\u0443\u044e \u0438 \u043e\u0431\u043e\u0431\u0449\u0451\u043d\u043d\u0443\u044e <code>point: PyObject<\/code> \u0432\u043e \u0447\u0442\u043e-\u0442\u043e, \u0441 \u0447\u0435\u043c \u043c\u044b \u0441\u043c\u043e\u0436\u0435\u043c \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c.<\/p>\n<p>  \u0422\u043e\u0447\u043d\u043e \u0442\u0430\u043a \u0436\u0435, \u043a\u0430\u043a \u043c\u044b \u043f\u043e\u043f\u0440\u043e\u0441\u0438\u043b\u0438 \u0443 PyO3 <code>Vec<\/code> \u043e\u0431\u044a\u0435\u043a\u0442\u0430 <code>PyObject<\/code>, \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043f\u043e\u043f\u0440\u043e\u0441\u0438\u0442\u044c numpy-array, \u0438 \u043e\u043d \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u0443\u0435\u0442 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442.<\/p>\n<pre><code class=\"rust\">use numpy::PyReadonlyArray1;  #[pyfunction] fn find_close_polygons(     \/\/ \u041e\u0431\u044a\u0435\u043a\u0442, \u0433\u043e\u0432\u043e\u0440\u044f\u0449\u0438\u0439 \"\u0423 \u043c\u0435\u043d\u044f \u0435\u0441\u0442\u044c GIL\", \u0447\u0442\u043e\u0431\u044b \u043c\u044b \u043c\u043e\u0433\u043b\u0438 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c\u043e\u0439 Python \u043f\u0430\u043c\u044f\u0442\u0438.     py: Python&lt;'_>,     polygons: Vec&lt;PyObject>,     \/\/ \u0421\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043c\u0430\u0441\u0441\u0438\u0432 numpy, \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043c\u044b \u0441\u043c\u043e\u0436\u0435\u043c \u0438\u043c\u0435\u0442\u044c.     point: PyReadonlyArray1&lt;f64>,     max_dist: f64, ) -> PyResult&lt;Vec&lt;PyObject>> {     \/\/ \u041f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u0443\u0435\u043c \u0432 \u043f\u043e\u043b\u043d\u043e\u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u044b\u0439 \u043d\u0430\u0442\u0438\u0432\u043d\u044b\u0439 \u043c\u0430\u0441\u0441\u0438\u0432 \"ndarray::ArrayView1\".     let point = point.as_array();     ... }<\/code><\/pre>\n<p>  \u0422\u0430\u043a \u043a\u0430\u043a \u0442\u043e\u0447\u043a\u0430 \u0442\u0435\u043f\u0435\u0440\u044c \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0432 ArrayView1, \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0435\u0451 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440:<\/p>\n<pre><code class=\"rust\">\/\/ \u0434\u0435\u043b\u0430\u0435\u043c \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u044e \"norm\". use ndarray_linalg::Norm;  assert_eq!((point.to_owned() - point).norm(), 0.);<\/code><\/pre>\n<p>  \u0422\u0435\u043f\u0435\u0440\u044c \u043d\u0430\u043c \u043f\u0440\u043e\u0441\u0442\u043e \u043d\u0443\u0436\u043d\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0446\u0435\u043d\u0442\u0440 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043c\u043d\u043e\u0433\u043e\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a\u0430 \u0438 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u0442\u044c \u0435\u0433\u043e \u0432 <code>ArrayView1<\/code>.<\/p>\n<p>  \u041d\u0430 PyO3 \u044d\u0442\u043e \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0442\u0430\u043a:<\/p>\n<pre><code class=\"rust\">let center = poly   .getattr(py, \"center\")?                 \/\/ getattr \u0432 \u0441\u0442\u0438\u043b\u0435 Python, \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0442\u043e\u043a\u0435\u043d GIL (`py`).   .extract::&lt;PyReadonlyArray1&lt;f64>>(py)?  \/\/ \u0421\u043e\u043e\u0431\u0449\u0430\u0435\u043c PyO3, \u0432\u043e \u0447\u0442\u043e \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u0442\u044c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442.   .as_array()                             \/\/ \u041a\u0430\u043a \"point\" \u0440\u0430\u043d\u0435\u0435.   .to_owned();                            \/\/ \u041d\u0430\u043c \u043d\u0443\u0436\u043d\u043e, \u0447\u0442\u043e\u0431\u044b \u043e\u0434\u043d\u043e\u0439 \u0438\u0437 \u0441\u0442\u043e\u0440\u043e\u043d `-` \"\u0432\u043b\u0430\u0434\u0435\u043b\u0438\".<\/code><\/pre>\n<p>  \u0421\u043b\u0435\u0433\u043a\u0430 \u043c\u043d\u043e\u0433\u043e\u0441\u043b\u043e\u0432\u043d\u043e, \u043d\u043e \u0432 \u0446\u0435\u043b\u043e\u043c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442, \u043e\u0447\u0435\u0432\u0438\u0434\u043d\u043e, \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043f\u043e\u0441\u0442\u0440\u043e\u0447\u043d\u043e\u0439 \u0442\u0440\u0430\u043d\u0441\u043b\u044f\u0446\u0438\u0435\u0439 \u043f\u0435\u0440\u0432\u043e\u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430:<\/p>\n<pre><code class=\"rust\">use pyo3::prelude::*;  use ndarray_linalg::Norm; use numpy::PyReadonlyArray1;  #[pyfunction] fn find_close_polygons(     py: Python&lt;'_>,     polygons: Vec&lt;PyObject>,     point: PyReadonlyArray1&lt;f64>,     max_dist: f64, ) -> PyResult&lt;Vec&lt;PyObject>> {     let mut close_polygons = vec![];     let point = point.as_array();     for poly in polygons {         let center = poly             .getattr(py, \"center\")?             .extract::&lt;PyReadonlyArray1&lt;f64>>(py)?             .as_array()             .to_owned();          if (center - point).norm() &lt; max_dist {             close_polygons.push(poly)         }     }      Ok(close_polygons) }<\/code><\/pre>\n<p>  \u0421\u0440\u0430\u0432\u043d\u0438\u043c \u0441 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b\u043e\u043c:<\/p>\n<pre><code class=\"python\">def find_close_polygons(     polygon_subset: List[Polygon], point: np.array, max_dist: float ) -> List[Polygon]:     close_polygons = []     for poly in polygon_subset:         if np.linalg.norm(poly.center - point) &lt; max_dist:             close_polygons.append(poly)      return close_polygons<\/code><\/pre>\n<p>  \u041c\u044b \u043e\u0436\u0438\u0434\u0430\u0435\u043c, \u0447\u0442\u043e \u044d\u0442\u0430 \u0432\u0435\u0440\u0441\u0438\u044f \u0431\u0443\u0434\u0435\u0442 \u0438\u043c\u0435\u0442\u044c \u043f\u0440\u0435\u0438\u043c\u0443\u0449\u0435\u0441\u0442\u0432\u0430 \u043f\u0435\u0440\u0435\u0434 \u0438\u0441\u0445\u043e\u0434\u043d\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0435\u0439, \u043d\u043e \u043d\u0430\u0441\u043a\u043e\u043b\u044c\u043a\u043e?<\/p>\n<pre><code class=\"bash\">$ (cd .\/poly_match_rs\/ &amp;&amp; maturin develop) $ python measure.py Took an avg of 609.46ms per iteration<\/code><\/pre>\n<p>  \u0422\u043e \u0435\u0441\u0442\u044c\u2026 Rust \u043e\u0447\u0435\u043d\u044c \u043c\u0435\u0434\u043b\u0435\u043d\u043d\u044b\u0439? \u041d\u0435\u0442! \u041c\u044b \u043f\u0440\u043e\u0441\u0442\u043e \u0437\u0430\u0431\u044b\u043b\u0438 \u0443\u0437\u043d\u0430\u0442\u044c \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c! \u0415\u0441\u043b\u0438 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043c \u043a\u043e\u0434 \u0441 <code>maturin develop --release<\/code>, \u0442\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u043c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u0433\u043e\u0440\u0430\u0437\u0434\u043e \u043b\u0443\u0447\u0448\u0435:<\/p>\n<pre><code class=\"bash\">$ (cd .\/poly_match_rs\/ &amp;&amp; maturin develop --release) $ python measure.py Took an avg of 23.44ms per iteration<\/code><\/pre>\n<p>  \u0410 \u0432\u043e\u0442 <em>\u044d\u0442\u043e<\/em> \u0443\u0436\u0435 \u0445\u043e\u0440\u043e\u0448\u0435\u0435 \u0443\u0441\u043a\u043e\u0440\u0435\u043d\u0438\u0435!<\/p>\n<p>  \u0422\u0430\u043a\u0436\u0435 \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u0438\u043c\u0435\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0437\u0430\u0433\u043b\u044f\u0434\u044b\u0432\u0430\u0442\u044c \u0432 \u043d\u0430\u0442\u0438\u0432\u043d\u044b\u0439 \u043a\u043e\u0434, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0432\u043a\u043b\u044e\u0447\u0438\u043c \u043e\u0442\u043b\u0430\u0434\u043e\u0447\u043d\u044b\u0435 \u0441\u0438\u043c\u0432\u043e\u043b\u044b \u0432 \u0440\u0435\u043b\u0438\u0437\u0435. \u0418 \u0437\u0430\u043e\u0434\u043d\u043e \u0441\u043f\u0440\u043e\u0441\u0438\u043c <em>\u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0443\u044e \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c<\/em>.<\/p>\n<pre><code class=\"bash\"># added to Cargo.toml [profile.release] debug = true       # \u041e\u0442\u043b\u0430\u0434\u043e\u0447\u043d\u044b\u0435 \u0441\u0438\u043c\u0432\u043e\u043b\u044b \u0434\u043b\u044f \u043d\u0430\u0448\u0435\u0433\u043e \u043f\u0440\u043e\u0444\u0438\u043b\u0438\u0440\u043e\u0432\u0449\u0438\u043a\u0430. lto = true         # \u041e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u044f \u044d\u0442\u0430\u043f\u0430 \u043a\u043e\u043c\u043f\u043e\u043d\u043e\u0432\u043a\u0438. codegen-units = 1  # \u0411\u043e\u043b\u0435\u0435 \u043c\u0435\u0434\u043b\u0435\u043d\u043d\u0430\u044f \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u044f, \u0437\u0430\u0442\u043e \u0431\u043e\u043b\u0435\u0435 \u0431\u044b\u0441\u0442\u0440\u044b\u0439 \u043a\u043e\u0434. <\/code><\/pre>\n<p>  <\/p>\n<h2><font color=\"#3AC1EF\">\u258d v2 \u2014 \u043f\u0435\u0440\u0435\u043f\u0438\u0448\u0435\u043c \u0435\u0449\u0451 \u0431\u043e\u043b\u044c\u0448\u0435 \u043d\u0430 Rust<\/font><\/h2>\n<p>  \u0422\u0435\u043f\u0435\u0440\u044c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0432 \u0444\u043b\u0430\u0433 <code>--native<\/code> \u0432 <code>py-spy<\/code>, \u043c\u044b \u0441\u043c\u043e\u0436\u0435\u043c \u0432\u0438\u0434\u0435\u0442\u044c \u0438 Python, \u0438 \u043d\u0430\u0448 \u043d\u043e\u0432\u044b\u0439 \u043d\u0430\u0442\u0438\u0432\u043d\u044b\u0439 \u043a\u043e\u0434.<\/p>\n<p>  \u0421\u043d\u043e\u0432\u0430 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c <code>py-spy<\/code>:<\/p>\n<pre><code class=\"bash\">$ py-spy record --native -o profile.svg -- python measure.py py-spy> Sampling process 100 times a second. Press Control-C to exit.<\/code><\/pre>\n<p>  \u041f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0442\u0430\u043a\u043e\u0439 flamegraph (\u043d\u0435\u043a\u0440\u0430\u0441\u043d\u044b\u0435 \u0446\u0432\u0435\u0442\u0430 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u044b \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u043c\u044b \u043c\u043e\u0433\u043b\u0438 \u043e\u0442\u0442\u0430\u043b\u043a\u0438\u0432\u0430\u0442\u044c\u0441\u044f \u043e\u0442 \u043d\u0438\u0445):<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/h7\/0k\/bp\/h70kbpauzzyg6fpuvbjhgiyi-90.png\" data-src=\"https:\/\/habrastorage.org\/webt\/h7\/0k\/bp\/h70kbpauzzyg6fpuvbjhgiyi-90.png\"\/><i><font color=\"#999999\">\u0418\u043d\u0442\u0435\u0440\u0430\u043a\u0442\u0438\u0432\u043d\u0443\u044e \u0432\u0435\u0440\u0441\u0438\u044e \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c <a href=\"https:\/\/ohadravid.github.io\/posts\/2023-03-rusty-python\/#v2---rewrite-even-more-in-rust\">\u0437\u0434\u0435\u0441\u044c<\/a><\/font><\/i><\/p>\n<p>  \u041f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0432 \u043d\u0430 \u0432\u044b\u0432\u043e\u0434 \u043f\u0440\u043e\u0444\u0438\u043b\u0438\u0440\u043e\u0432\u0449\u0438\u043a\u0430, \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0437\u0430\u043c\u0435\u0442\u0438\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u044b\u0445 \u043c\u043e\u043c\u0435\u043d\u0442\u043e\u0432:<\/p>\n<ol>\n<li>\u041e\u0442\u043d\u043e\u0441\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u0440\u0430\u0437\u043c\u0435\u0440 <code>find_close_polygons::...::trampoline<\/code> (\u0441\u0438\u043c\u0432\u043e\u043b\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 Python \u043d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442) \u0438 <code>__pyfunction_find_close_polygons<\/code> (\u043d\u0430\u0448\u0435\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438).\n<ul>\n<li>\u0415\u0441\u043b\u0438 \u043d\u0430\u0432\u0435\u0441\u0442\u0438 \u043c\u044b\u0448\u044c, \u0432\u0438\u0434\u043d\u043e, \u0447\u0442\u043e \u0441\u044d\u043c\u043f\u043b\u044b \u0441\u043e\u043e\u0442\u043d\u043e\u0441\u044f\u0442\u0441\u044f \u043a\u0430\u043a 95% \u0438 88%, \u0442\u043e \u0435\u0441\u0442\u044c \u043b\u0438\u0448\u043d\u044f\u044f \u0442\u0440\u0430\u0442\u0430 \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432 \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u043c\u0430\u043b\u0430.<\/li>\n<\/ul>\n<\/li>\n<li>\u0421\u0430\u043c\u0430 \u043b\u043e\u0433\u0438\u043a\u0430 (<code>if (center - point).norm() &lt; max_dist { ... }<\/code>), \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0432 <code>lib_v1.rs:22<\/code> (\u043e\u0447\u0435\u043d\u044c \u043c\u0430\u043b\u0435\u043d\u044c\u043a\u0438\u0439 \u043f\u0440\u044f\u043c\u043e\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a \u0441\u043f\u0440\u0430\u0432\u0430), \u0437\u0430\u043d\u0438\u043c\u0430\u0435\u0442 \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e 9% \u043e\u0442 \u0432\u0441\u0435\u0433\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0438\u0441\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f.\n<ul>\n<li>\u0422\u043e \u0435\u0441\u0442\u044c \u0443\u043b\u0443\u0447\u0448\u0435\u043d\u0438\u0435 \u0432 \u0434\u0435\u0441\u044f\u0442\u044c \u0440\u0430\u0437 \u0432\u0441\u0451 \u0440\u0430\u0432\u043d\u043e \u0434\u043e\u043b\u0436\u043d\u043e \u0431\u044b\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e!<\/li>\n<\/ul>\n<\/li>\n<li>\u041e\u0441\u043d\u043e\u0432\u043d\u0430\u044f \u0447\u0430\u0441\u0442\u044c \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0442\u0440\u0430\u0442\u0438\u0442\u0441\u044f \u043d\u0430 <code>lib_v1.rs:16<\/code>, \u0442\u043e \u0435\u0441\u0442\u044c \u043d\u0430 <code>poly.getattr(...).extract(...)<\/code>, \u0438 \u0435\u0441\u043b\u0438 \u043c\u044b \u043f\u0440\u0438\u0431\u043b\u0438\u0437\u0438\u043c \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435, \u0442\u043e \u0443\u0432\u0438\u0434\u0438\u043c, \u0447\u0442\u043e \u043d\u0430 \u0441\u0430\u043c\u043e\u043c \u0434\u0435\u043b\u0435 \u044d\u0442\u043e \u043f\u0440\u043e\u0441\u0442\u043e <code>getattr<\/code> \u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0435\u0433\u043e \u043c\u0430\u0441\u0441\u0438\u0432\u0430 \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 <code>as_array<\/code>.<\/li>\n<\/ol>\n<p>  \u041c\u043e\u0436\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0432\u044b\u0432\u043e\u0434, \u0447\u0442\u043e \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0441\u043e\u0441\u0440\u0435\u0434\u043e\u0442\u043e\u0447\u0438\u0442\u044c\u0441\u044f \u043d\u0430 \u0440\u0435\u0448\u0435\u043d\u0438\u0438 \u0442\u0440\u0435\u0442\u044c\u0435\u0433\u043e \u043f\u0443\u043d\u043a\u0442\u0430, \u0438 \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u044d\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u041f\u0435\u0440\u0435\u043f\u0438\u0441\u0430\u0432 <code>Polygon<\/code> \u043d\u0430 Rust.<\/p>\n<p>  \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0432\u0437\u0433\u043b\u044f\u043d\u0435\u043c \u043d\u0430 \u043d\u0430\u0448\u0443 \u0446\u0435\u043b\u044c:<\/p>\n<pre><code class=\"python\">@dataclass class Polygon:     x: np.array     y: np.array     _area: float = None      @cached_property     def center(self) -> np.array:         centroid = np.array([self.x, self.y]).mean(axis=1)         return centroid      def area(self) -> float:         if self._area is None:             self._area = 0.5 * np.abs(                 np.dot(self.x, np.roll(self.y, 1)) - np.dot(self.y, np.roll(self.x, 1))             )         return self._area<\/code><\/pre>\n<p>  \u041d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0438\u043c\u0435\u044e\u0449\u0438\u0439\u0441\u044f API, \u043d\u043e \u043d\u0430\u043c \u043d\u0435 \u043d\u0443\u0436\u043d\u043e (\u043f\u043e\u043a\u0430), \u0447\u0442\u043e\u0431\u044b <code>area<\/code> \u0431\u044b\u043b\u0430 \u0442\u0430\u043a\u043e\u0439 \u0443\u0436 \u0431\u044b\u0441\u0442\u0440\u043e\u0439.<\/p>\n<p>  \u0421\u0430\u043c \u043a\u043b\u0430\u0441\u0441 \u043c\u043e\u0436\u0435\u0442 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0441\u043b\u043e\u0436\u043d\u044b\u0435 \u0432\u0435\u0449\u0438, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043c\u0435\u0442\u043e\u0434 <code>merge<\/code>, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0449\u0438\u0439 <code>ConvexHull<\/code> \u0438\u0437 <code>scipy.spatial<\/code>.<\/p>\n<p>  \u0427\u0442\u043e\u0431\u044b \u0441\u043d\u0438\u0437\u0438\u0442\u044c \u0437\u0430\u0442\u0440\u0430\u0442\u044b (\u0438 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u0442\u044c \u0440\u0430\u043c\u043a\u0438 \u044d\u0442\u043e\u0439 \u0438 \u0442\u0430\u043a \u0434\u043b\u0438\u043d\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0438), \u043c\u044b \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u0435\u0440\u0435\u043c\u0435\u0441\u0442\u0438\u043c \u00ab\u043e\u0441\u043d\u043e\u0432\u043d\u0443\u044e\u00bb \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c <code>Polygon<\/code> \u043d\u0430 Rust, \u0438 \u0441\u0434\u0435\u043b\u0430\u0435\u043c \u0435\u0451 \u043f\u043e\u0434\u043a\u043b\u0430\u0441\u0441\u043e\u043c \u0438\u0437 Python \u0434\u043b\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u043e\u0433\u043e API.<\/p>\n<p>  \u041d\u0430\u0448\u0430 <code>struct<\/code> \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u0442\u0430\u043a:<\/p>\n<pre><code class=\"rust\">\/\/ \"Array1\" - \u044d\u0442\u043e \u043e\u0434\u043d\u043e\u043c\u0435\u0440\u043d\u044b\u0439 \u043c\u0430\u0441\u0441\u0438\u0432, \u0438 \u043a\u0440\u0435\u0439\u0442 \"numpy\" \u0431\u0443\u0434\u0435\u0442 \u0445\u043e\u0440\u043e\u0448\u043e \u0441 \u043d\u0438\u043c \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c. use ndarray::Array1;  \/\/ \"subclass\" \u043f\u0440\u0438\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 PyO3 \u0440\u0430\u0437\u0440\u0435\u0448\u0438\u0442\u044c \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043f\u043e\u0434\u043a\u043b\u0430\u0441\u0441\u043e\u0432 \u044d\u0442\u043e\u0433\u043e \u043d\u0430 Python. #[pyclass(subclass)] struct Polygon {     x: Array1&lt;f64>,     y: Array1&lt;f64>,     center: Array1&lt;f64>, }<\/code><\/pre>\n<p>  \u041c\u044b \u0445\u043e\u0442\u0438\u043c \u0440\u0430\u0441\u043a\u0440\u044b\u0442\u044c <code>poly.{x, y, center}<\/code> \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:<\/p>\n<ol>\n<li>\u0421\u0432\u043e\u0439\u0441\u0442\u0432\u0430.<\/li>\n<li>\u041c\u0430\u0441\u0441\u0438\u0432\u044b numpy.<\/li>\n<\/ol>\n<p>  \u0422\u0430\u043a\u0436\u0435 \u043d\u0430\u043c \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440, \u0447\u0442\u043e\u0431\u044b Python \u043c\u043e\u0433 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u043d\u043e\u0432\u044b\u0435 <code>Polygon<\/code>.<\/p>\n<pre><code class=\"rust\">use numpy::{PyArray1, PyReadonlyArray1, ToPyArray};  #[pymethods] impl Polygon {     #[new]     fn new(x: PyReadonlyArray1&lt;f64>, y: PyReadonlyArray1&lt;f64>) -> Polygon {         let x = x.as_array();         let y = y.as_array();         let center = Array1::from_vec(vec![x.mean().unwrap(), y.mean().unwrap()]);          Polygon {             x: x.to_owned(),             y: y.to_owned(),             center,         }     }          \/\/ \"Py&lt;..>\" \u0432 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c\u043e\u043c \u0442\u0438\u043f\u0435 - \u044d\u0442\u043e \u0441\u043f\u043e\u0441\u043e\u0431 \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c, \u0447\u0442\u043e \u043e\u0431\u044a\u0435\u043a\u0442 \u043f\u0440\u0438\u043d\u0430\u0434\u043b\u0435\u0436\u0438\u0442 Python\".     #[getter]                    fn x(&amp;self, py: Python&lt;'_>) -> PyResult&lt;Py&lt;PyArray1&lt;f64>>> {         Ok(self.x.to_pyarray(py).to_owned()) \/\/ \u0421\u043e\u0437\u0434\u0430\u0451\u043c numpy-\u0432\u0435\u0440\u0441\u0438\u044e \"x\", \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0431\u0443\u0434\u0435\u0442 \u0432\u043b\u0430\u0434\u0435\u0442\u044c Python.     }      \/\/ \u0422\u043e \u0436\u0435 \u0434\u043b\u044f \"y\" \u0438 \"center\". }<\/code><\/pre>\n<p>  \u041c\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043d\u0430\u0448\u0443 \u043d\u043e\u0432\u0443\u044e struct \u043a\u0430\u043a \u043a\u043b\u0430\u0441\u0441 \u0432 \u043c\u043e\u0434\u0443\u043b\u044c:<\/p>\n<pre><code class=\"rust\">#[pymodule] fn poly_match_rs(_py: Python, m: &amp;PyModule) -> PyResult&lt;()> {     m.add_class::&lt;Polygon>()?; \/\/ new.     m.add_function(wrap_pyfunction!(find_close_polygons, m)?)?;     Ok(()) }<\/code><\/pre>\n<p>  \u0410 \u0442\u0435\u043f\u0435\u0440\u044c \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u043a\u043e\u0434 \u043d\u0430 Python, \u0447\u0442\u043e\u0431\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0435\u0433\u043e:<\/p>\n<pre><code class=\"python\">class Polygon(poly_match_rs.Polygon):     _area: float = None      def area(self) -> float:         ...<\/code><\/pre>\n<p>  \u041c\u043e\u0436\u043d\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u044e, \u0438 \u044d\u0442\u043e \u043d\u0430 \u0441\u0430\u043c\u043e\u043c \u0434\u0435\u043b\u0435 \u0437\u0430\u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442, \u0442\u043e\u043b\u044c\u043a\u043e \u0433\u043e\u0440\u0430\u0437\u0434\u043e \u043c\u0435\u0434\u043b\u0435\u043d\u043d\u0435\u0435! (\u041f\u043e\u043c\u043d\u0438\u0442\u0435, \u0447\u0442\u043e <code>x<\/code>, <code>y<\/code> \u0438 <code>center<\/code> \u0442\u0435\u043f\u0435\u0440\u044c \u043d\u0443\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u043d\u043e\u0432\u044b\u0439 \u043c\u0430\u0441\u0441\u0438\u0432 numpy <strong>\u043f\u0440\u0438 \u043a\u0430\u0436\u0434\u043e\u0439 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 \u0434\u043e\u0441\u0442\u0443\u043f\u0430<\/strong>).<\/p>\n<p>  \u0427\u0442\u043e\u0431\u044b \u043f\u043e\u0432\u044b\u0441\u0438\u0442\u044c \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c, \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e <code>\u0438\u0437\u0432\u043b\u0435\u0447\u044c<\/code> \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0439 <code>Polygon<\/code> \u043d\u0430 Rust \u0438\u0437 \u0441\u043f\u0438\u0441\u043a\u0430 <code>Polygon<\/code> Python.<\/p>\n<p>  PyO3 \u043e\u0447\u0435\u043d\u044c \u0433\u0438\u0431\u043e\u043a \u0441 \u0442\u0430\u043a\u0438\u043c \u0442\u0438\u043f\u043e\u043c \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0439, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u044d\u0442\u043e \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u043c\u0438 \u0441\u043f\u043e\u0441\u043e\u0431\u0430\u043c\u0438. \u041e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435 \u0437\u0430\u043a\u043b\u044e\u0447\u0430\u0435\u0442\u0441\u044f \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u043d\u0430\u043c \u0442\u0430\u043a\u0436\u0435 \u043d\u0443\u0436\u043d\u043e \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0442\u044c <code>Polygon<\/code> \u044f\u0437\u044b\u043a\u0430 Python \u0438 \u043c\u044b \u043d\u0435 \u0445\u043e\u0442\u0438\u043c \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u043a\u043b\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0445.<\/p>\n<p>  \u041c\u043e\u0436\u043d\u043e \u0432\u0440\u0443\u0447\u043d\u0443\u044e \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c <code>.extract::&lt;Polygon>(py)?<\/code> \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e <code>PyObject<\/code>, \u043d\u043e \u043c\u044b \u043f\u043e\u043f\u0440\u043e\u0441\u0438\u043c PyO3 \u0434\u0430\u0432\u0430\u0442\u044c \u043d\u0430\u043c \u043d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e <code>Py&lt;Polygon><\/code>.<\/p>\n<p>  \u042d\u0442\u043e \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043f\u0440\u0438\u043d\u0430\u0434\u043b\u0435\u0436\u0430\u0449\u0438\u0439 Python \u043e\u0431\u044a\u0435\u043a\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439, \u043a\u0430\u043a \u043c\u044b \u043e\u0436\u0438\u0434\u0430\u0435\u043c, \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 (\u0438\u043b\u0438 \u0432 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043f\u043e\u0434\u043a\u043b\u0430\u0441\u0441) \u043d\u0430\u0442\u0438\u0432\u043d\u043e\u0439 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b <code>pyclass<\/code>.<\/p>\n<pre><code class=\"rust\">#[pyfunction] fn find_close_polygons(     py: Python&lt;'_>,     polygons: Vec&lt;Py&lt;Polygon>>,             \/\/ \u0421\u0441\u044b\u043b\u043a\u0438 \u043d\u0430 \u043e\u0431\u044a\u0435\u043a\u0442\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u043c\u0438 \u0432\u043b\u0430\u0434\u0435\u0435\u0442 Python.     point: PyReadonlyArray1&lt;f64>,     max_dist: f64, ) -> PyResult&lt;Vec&lt;Py&lt;Polygon>>> {           \/\/ \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0442\u0435 \u0436\u0435 \u0441\u0441\u044b\u043b\u043a\u0438 \u043d\u0430 \"Py\" \u0431\u0435\u0437 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439.     let mut close_polygons = vec![];     let point = point.as_array();     for poly in polygons {         let center = poly.borrow(py).center \/\/ \u0414\u043e\u043b\u0436\u0435\u043d \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c GIL (\"py\"), \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u0437\u0430\u0438\u043c\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0438\u0439 \"Polygon\".             .to_owned();          if (center - point).norm() &lt; max_dist {             close_polygons.push(poly)         }     }      Ok(close_polygons) }<\/code><\/pre>\n<p>  \u041f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c, \u0447\u0435\u0433\u043e \u043c\u044b \u0434\u043e\u0431\u0438\u043b\u0438\u0441\u044c \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 \u044d\u0442\u043e\u0433\u043e \u043a\u043e\u0434\u0430:<\/p>\n<pre><code class=\"bash\">$ python measure.py Took an avg of 6.29ms per iteration<\/code><\/pre>\n<p>  \u041c\u044b \u043f\u043e\u0447\u0442\u0438 \u0443 \u0446\u0435\u043b\u0438! \u041e\u0441\u0442\u0430\u043b\u043e\u0441\u044c \u0443\u0434\u0432\u043e\u0438\u0442\u044c \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c!<\/p>\n<h2><font color=\"#3AC1EF\">\u258d v3 \u2014 \u0438\u0437\u0431\u0435\u0433\u0430\u0435\u043c \u0440\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0439<\/font><\/h2>\n<p>  \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0435\u0449\u0451 \u0440\u0430\u0437 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043c \u043f\u0440\u043e\u0444\u0438\u043b\u0438\u0440\u043e\u0432\u0449\u0438\u043a.<\/p>\n<div style=\"text-align:center;\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/cy\/up\/yk\/cyupykcpwvnv-wsuytw1se3-fw8.png\" data-src=\"https:\/\/habrastorage.org\/webt\/cy\/up\/yk\/cyupykcpwvnv-wsuytw1se3-fw8.png\"\/><\/div>\n<p><i><font color=\"#999999\">\u0418\u043d\u0442\u0435\u0440\u0430\u043a\u0442\u0438\u0432\u043d\u0430\u044f \u0432\u0435\u0440\u0441\u0438\u044f \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f <a href=\"https:\/\/ohadravid.github.io\/posts\/2023-03-rusty-python\/#v3---avoid-allocations\">\u0437\u0434\u0435\u0441\u044c<\/a><\/font><\/i><\/p>\n<ol>\n<li>\u041c\u044b \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u043c \u0432\u0438\u0434\u0435\u0442\u044c <code>select_best_polygon<\/code>, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0442\u0435\u043f\u0435\u0440\u044c \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442 \u043a\u0430\u043a\u043e\u0439-\u0442\u043e \u043a\u043e\u0434 \u043d\u0430 Rust (\u043a\u043e\u0433\u0434\u0430 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u0432\u0435\u043a\u0442\u043e\u0440\u044b <code>x<\/code> \u0438 <code>y<\/code>)\n<ul>\n<li>\u041c\u043e\u0436\u043d\u043e \u044d\u0442\u043e \u0438\u0441\u043f\u0440\u0430\u0432\u0438\u0442\u044c, \u043d\u043e \u043f\u043e\u0442\u0435\u043d\u0446\u0438\u0430\u043b \u044d\u0442\u043e\u0433\u043e \u0443\u043b\u0443\u0447\u0448\u0435\u043d\u0438\u044f \u043e\u0447\u0435\u043d\u044c \u043c\u0430\u043b (\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e, 10%)<\/li>\n<\/ul>\n<\/li>\n<li>\u041c\u044b \u0432\u0438\u0434\u0438\u043c, \u0447\u0442\u043e \u0442\u0440\u0430\u0442\u0438\u043c \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e 20% \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0432 <code>extract_argument<\/code> (\u0432 <code>lib_v2.rs:48<\/code>), \u0442\u043e \u0435\u0441\u0442\u044c \u043b\u0438\u0448\u043d\u044f\u044f \u0442\u0440\u0430\u0442\u0430 \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432 \u043f\u043e-\u043f\u0440\u0435\u0436\u043d\u0435\u043c\u0443 \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0432\u0435\u043b\u0438\u043a\u0430!\n<ul>\n<li>\u041d\u043e \u0431\u041e\u043b\u044c\u0448\u0430\u044f \u0447\u0430\u0441\u0442\u044c \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0442\u0440\u0430\u0442\u0438\u0442\u0441\u044f \u043d\u0430 <code>PyIterator::next<\/code> \u0438 <code>PyTypeInfo::is_type_of<\/code>, \u0447\u0442\u043e \u0438\u0441\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u043d\u0435 \u0442\u0430\u043a \u043f\u0440\u043e\u0441\u0442\u043e.<\/li>\n<\/ul>\n<\/li>\n<li>\u041c\u044b \u0432\u0438\u0434\u0438\u043c, \u0447\u0442\u043e \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u043c\u043d\u043e\u0433\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0442\u0440\u0430\u0442\u0438\u0442\u0441\u044f \u043d\u0430 \u0440\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435!\n<ul>\n<li><code>lib_v2.rs:58<\/code> \u2014 \u044d\u0442\u043e \u043d\u0430\u0448 <code>if<\/code>, \u0438 \u043c\u044b \u0432\u0438\u0434\u0438\u043c <code>drop_in_place<\/code> \u0438 <code>to_owned<\/code>.<\/li>\n<li>\u0412\u0441\u0435\u0433\u043e \u044d\u0442\u043e \u043e\u043a\u043e\u043b\u043e 35% \u043e\u0442 \u0441\u0443\u043c\u043c\u0430\u0440\u043d\u043e\u0433\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438, \u0447\u0442\u043e \u0433\u043e\u0440\u0430\u0437\u0434\u043e \u0431\u043e\u043b\u044c\u0448\u0435, \u0447\u0435\u043c \u043c\u044b \u043e\u0436\u0438\u0434\u0430\u043b\u0438: \u043f\u0440\u0438 \u043d\u0430\u043b\u0438\u0447\u0438\u0438 \u0432\u0441\u0435\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 \u044d\u0442\u043e \u0434\u043e\u043b\u0436\u043d\u0430 \u0431\u044b\u0442\u044c \u0431\u044b\u0441\u0442\u0440\u0430\u044f \u0447\u0430\u0441\u0442\u044c \u043a\u043e\u0434\u0430.<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n<p>  \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0440\u0430\u0437\u0431\u0435\u0440\u0451\u043c\u0441\u044f \u0441 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u043c \u043f\u0443\u043d\u043a\u0442\u043e\u043c.<\/p>\n<p>  \u0412\u043e\u0442 \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442 \u043a\u043e\u0434\u0430, \u0432\u044b\u0437\u044b\u0432\u0430\u044e\u0449\u0438\u0439 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b:<\/p>\n<pre><code class=\"rust\">let center = poly.borrow(py).center     .to_owned();  if (center - point).norm() &lt; max_dist { ... } <\/code><\/pre>\n<p>  \u041c\u044b \u0445\u043e\u0442\u0438\u043c \u0438\u0437\u0431\u0435\u0436\u0430\u0442\u044c \u0432\u043e\u0442 \u044d\u0442\u043e\u0433\u043e <code>to_owned<\/code>. \u041d\u043e \u043d\u0430\u043c \u043d\u0443\u0436\u0435\u043d owned-\u043e\u0431\u044a\u0435\u043a\u0442 \u0434\u043b\u044f <code>norm<\/code>, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043f\u0440\u0438\u0434\u0451\u0442\u0441\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0435\u0433\u043e \u0432\u0440\u0443\u0447\u043d\u0443\u044e.<\/p>\n<p>  (\u041f\u0440\u0438\u0447\u0438\u043d\u0430 \u0442\u043e\u0433\u043e, \u0447\u0442\u043e \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0443\u043b\u0443\u0447\u0448\u0438\u0442\u044c <code>ndarray<\/code>, \u0437\u0430\u043a\u043b\u044e\u0447\u0430\u0435\u0442\u0441\u044f \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u043c\u044b \u0437\u043d\u0430\u0435\u043c, \u0447\u0442\u043e \u043d\u0430\u0448 \u043c\u0430\u0441\u0441\u0438\u0432 \u043d\u0430 \u0441\u0430\u043c\u043e\u043c \u0434\u0435\u043b\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0441\u043e\u0431\u043e\u0439 \u0434\u0432\u0430 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f <code>f32<\/code>).<\/p>\n<p>  \u042d\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u0442\u0430\u043a:<\/p>\n<pre><code class=\"rust\">use ndarray_linalg::Scalar;  let center = &amp;poly.as_ref(py).borrow().center;  if ((center[0] - point[0]).square() + (center[1] - point[1]).square()).sqrt() &lt; max_dist {     close_polygons.push(poly) }<\/code><\/pre>\n<p>  \u041d\u043e, \u0443\u0432\u044b, borrow checker \u043d\u0430\u043c\u0438 \u043d\u0435\u0434\u043e\u0432\u043e\u043b\u0435\u043d:<\/p>\n<pre><code class=\"plaintext\">error[E0505]: cannot move out of `poly` because it is borrowed   --> src\/lib.rs:58:33    | 55 |         let center = &amp;poly.as_ref(py).borrow().center;    |                       ------------------------    |                       |    |                       borrow of `poly` occurs here    |                       a temporary with access to the borrow is created here ... ... 58 |             close_polygons.push(poly);    |                                 ^^^^ move out of `poly` occurs here 59 |         } 60 |     }    |     - ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `PyRef`<\/code><\/pre>\n<p>  \u041a\u0430\u043a \u043e\u0431\u044b\u0447\u043d\u043e, borrow checker \u043f\u0440\u0430\u0432: \u043c\u044b \u0441\u043e\u0432\u0435\u0440\u0448\u0430\u0435\u043c \u043f\u0440\u0435\u0441\u0442\u0443\u043f\u043b\u0435\u043d\u0438\u044f \u0441 \u043f\u0430\u043c\u044f\u0442\u044c\u044e.<\/p>\n<p>  \u041f\u0440\u043e\u0449\u0435 \u0432\u0441\u0435\u0433\u043e \u0438\u0441\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u044d\u0442\u043e \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 <em>Just Clone<\/em>, \u043f\u043e\u0441\u043b\u0435 \u0447\u0435\u0433\u043e <code>close_polygons.push(poly.clone())<\/code> \u0441\u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u0443\u0435\u0442\u0441\u044f.<\/p>\n<p>  \u041d\u0430 \u0441\u0430\u043c\u043e\u043c \u0434\u0435\u043b\u0435, \u044d\u0442\u043e \u043e\u0447\u0435\u043d\u044c \u043c\u0430\u043b\u043e\u0437\u0430\u0442\u0440\u0430\u0442\u043d\u044b\u0439 \u043a\u043b\u043e\u043d, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u043c\u044b \u0432\u0441\u0435\u0433\u043e \u043b\u0438\u0448\u044c \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c <code>incr<\/code> \u0441\u0447\u0451\u0442\u0447\u0438\u043a\u0430 \u0441\u0441\u044b\u043b\u043e\u043a \u043e\u0431\u044a\u0435\u043a\u0442\u0430 Python.<\/p>\n<p>  \u041e\u0434\u043d\u0430\u043a\u043e \u0432 \u044d\u0442\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0441\u043e\u043a\u0440\u0430\u0442\u0438\u0442\u044c borrow, \u0441\u0434\u0435\u043b\u0430\u0432 \u043a\u043b\u0430\u0441\u0441\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u0442\u0440\u044e\u043a Rust:<\/p>\n<pre><code class=\"rust\">let norm = {     let center = &amp;poly.as_ref(py).borrow().center;      ((center[0] - point[0]).square() + (center[1] - point[1]).square()).sqrt() };  if norm &lt; max_dist {     close_polygons.push(poly) }<\/code><\/pre>\n<p>  \u0422\u0430\u043a \u043a\u0430\u043a <code>poly<\/code> \u0437\u0430\u0438\u043c\u0441\u0442\u0432\u0443\u0435\u0442\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u0432\u043e \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0435\u0439 \u043e\u0431\u043b\u0430\u0441\u0442\u0438 \u0432\u0438\u0434\u0438\u043c\u043e\u0441\u0442\u0438, \u043f\u043e\u0441\u043b\u0435 \u0442\u043e\u0433\u043e \u043a\u0430\u043a \u043c\u044b \u0434\u043e\u0441\u0442\u0438\u0433\u043d\u0435\u043c <code>close_polygons.push<\/code>, \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440 \u0441\u043c\u043e\u0436\u0435\u0442 \u0443\u0437\u043d\u0430\u0442\u044c, \u0447\u0442\u043e \u043c\u044b \u0431\u043e\u043b\u044c\u0448\u0435 \u043d\u0435 \u0445\u0440\u0430\u043d\u0438\u043c \u044d\u0442\u0443 \u0441\u0441\u044b\u043b\u043a\u0443 \u0438 \u0441\u043f\u043e\u043a\u043e\u0439\u043d\u043e \u0441\u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u0443\u0435\u0442 \u043d\u043e\u0432\u0443\u044e \u0432\u0435\u0440\u0441\u0438\u044e.<\/p>\n<p>  \u041d\u0430\u043a\u043e\u043d\u0435\u0446, \u043c\u044b \u0434\u043e\u0431\u0438\u043b\u0438\u0441\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0433\u043e:<\/p>\n<pre><code class=\"bash\">$ python measure.py Took an avg of 2.90ms per iteration<\/code><\/pre>\n<p>  \u0421\u0442\u043e\u043a\u0440\u0430\u0442\u043d\u043e\u0435 \u0443\u043b\u0443\u0447\u0448\u0435\u043d\u0438\u0435 \u043f\u043e \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044e \u0441 \u043f\u0435\u0440\u0432\u043e\u043d\u0430\u0447\u0430\u043b\u044c\u043d\u044b\u043c \u043a\u043e\u0434\u043e\u043c.<\/p>\n<h2><font color=\"#3AC1EF\">\u258d \u041f\u043e\u0434\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u0438\u0442\u043e\u0433\u043e\u0432<\/font><\/h2>\n<p>  \u041c\u044b \u043d\u0430\u0447\u0438\u043d\u0430\u043b\u0438 \u0441 \u0442\u0430\u043a\u043e\u0433\u043e \u043a\u043e\u0434\u0430 \u043d\u0430 Python:<\/p>\n<pre><code class=\"python\">@dataclass class Polygon:     x: np.array     y: np.array     _area: float = None      @cached_property     def center(self) -> np.array:         centroid = np.array([self.x, self.y]).mean(axis=1)         return centroid      def area(self) -> float:         ...  def find_close_polygons(     polygon_subset: List[Polygon], point: np.array, max_dist: float ) -> List[Polygon]:     close_polygons = []     for poly in polygon_subset:         if np.linalg.norm(poly.center - point) &lt; max_dist:             close_polygons.append(poly)      return close_polygons  # \u041e\u0441\u0442\u0430\u043b\u044c\u043d\u0430\u044f \u0447\u0430\u0441\u0442\u044c \u0444\u0430\u0439\u043b\u0430 (main, select_best_polygon).<\/code><\/pre>\n<p>  \u041c\u044b \u043f\u0440\u043e\u0444\u0438\u043b\u0438\u0440\u043e\u0432\u0430\u043b\u0438 \u0435\u0433\u043e \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 <code>py-spy<\/code>, \u0438 \u0434\u0430\u0436\u0435 \u0441\u0430\u043c\u0430\u044f \u043d\u0430\u0438\u0432\u043d\u0430\u044f \u043f\u043e\u0441\u0442\u0440\u043e\u0447\u043d\u0430\u044f \u0442\u0440\u0430\u043d\u0441\u043b\u044f\u0446\u0438\u044f <code>find_close_polygons<\/code> \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u043b\u0430 \u0443\u043b\u0443\u0447\u0448\u0435\u043d\u0438\u0435 \u0432 \u0434\u0435\u0441\u044f\u0442\u044c \u0441 \u043b\u0438\u0448\u043d\u0438\u043c \u0440\u0430\u0437.<\/p>\n<p>  \u041c\u044b \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u043b\u0438 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0438\u0442\u0435\u0440\u0430\u0446\u0438\u0439 \u00ab\u043f\u0440\u043e\u0444\u0438\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435-\u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u043a\u043e\u0434\u0430-\u0438\u0437\u043c\u0435\u0440\u0435\u043d\u0438\u044f\u00bb, \u043f\u043e\u043a\u0430 \u043d\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u0438 \u0441\u0442\u043e\u043a\u0440\u0430\u0442\u043d\u043e\u0435 \u0443\u043b\u0443\u0447\u0448\u0435\u043d\u0438\u0435 \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0438\u0441\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f, \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0432 \u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u0442\u043e\u0442 \u0436\u0435 API, \u0447\u0442\u043e \u0438 \u0443 \u0438\u0441\u0445\u043e\u0434\u043d\u043e\u0439 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438.<\/p>\n<div class=\"scrollable-table\">\n<table>\n<thead>\n<tr>\n<th>\u0412\u0435\u0440\u0441\u0438\u044f<\/th>\n<th>\u0421\u0440. \u0432\u0440\u0435\u043c\u044f \u043d\u0430 \u0438\u0442\u0435\u0440\u0430\u0446\u0438\u044e (\u043c\u0441)<\/th>\n<th>\u041c\u043d\u043e\u0436\u0438\u0442\u0435\u043b\u044c<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>\u0411\u0430\u0437\u043e\u0432\u0430\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f (\u043d\u0430 Python)<\/td>\n<td>293,41<\/td>\n<td>1x<\/td>\n<\/tr>\n<tr>\n<td>\u041d\u0430\u0438\u0432\u043d\u0430\u044f \u043f\u043e\u0441\u0442\u0440\u043e\u0447\u043d\u0430\u044f \u0442\u0440\u0430\u043d\u0441\u043b\u044f\u0446\u0438\u044f \u043d\u0430 Rust <code>find_close_polygons<\/code><\/td>\n<td>23,44<\/td>\n<td>12,50x<\/td>\n<\/tr>\n<tr>\n<td>\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f <code>Polygon<\/code> \u043d\u0430 Rust<\/td>\n<td>6,29<\/td>\n<td>46,53x<\/td>\n<\/tr>\n<tr>\n<td>\u041e\u043f\u0442\u0438\u043c\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u0430\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0440\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0439 \u043d\u0430 Rust<\/td>\n<td>2,90<\/td>\n<td>101,16x<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<p>\u041e\u043a\u043e\u043d\u0447\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u043a\u043e\u0434 \u043d\u0430 Python \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0442\u0430\u043a:<\/p>\n<pre><code class=\"python\">import poly_match_rs from poly_match_rs import find_close_polygons  class Polygon(poly_match_rs.Polygon):     _area: float = None      def area(self) -> float:         ...  # \u041e\u0441\u0442\u0430\u0432\u0448\u0430\u044f\u0441\u044f \u0447\u0430\u0441\u0442\u044c \u0444\u0430\u0439\u043b\u0430 \u043d\u0435 \u0438\u0437\u043c\u0435\u043d\u0438\u043b\u0430\u0441\u044c (main, select_best_polygon).<\/code><\/pre>\n<p>  \u041e\u043d \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u043a\u043e\u0434 \u043d\u0430 Rust:<\/p>\n<pre><code class=\"rust\">use pyo3::prelude::*;  use ndarray::Array1; use ndarray_linalg::Scalar; use numpy::{PyArray1, PyReadonlyArray1, ToPyArray};  #[pyclass(subclass)] struct Polygon {     x: Array1&lt;f64>,     y: Array1&lt;f64>,     center: Array1&lt;f64>, }  #[pymethods] impl Polygon {     #[new]     fn new(x: PyReadonlyArray1&lt;f64>, y: PyReadonlyArray1&lt;f64>) -> Polygon {         let x = x.as_array();         let y = y.as_array();         let center = Array1::from_vec(vec![x.mean().unwrap(), y.mean().unwrap()]);          Polygon {             x: x.to_owned(),             y: y.to_owned(),             center,         }     }      #[getter]     fn x(&amp;self, py: Python&lt;'_>) -> PyResult&lt;Py&lt;PyArray1&lt;f64>>> {         Ok(self.x.to_pyarray(py).to_owned())     }      \/\/ \u0422\u043e \u0436\u0435 \u0434\u043b\u044f \"y\" \u0438 \"center\". }  #[pyfunction] fn find_close_polygons(     py: Python&lt;'_>,     polygons: Vec&lt;Py&lt;Polygon>>,     point: PyReadonlyArray1&lt;f64>,     max_dist: f64, ) -> PyResult&lt;Vec&lt;Py&lt;Polygon>>> {     let mut close_polygons = vec![];     let point = point.as_array();     for poly in polygons {         let norm = {             let center = &amp;poly.as_ref(py).borrow().center;              ((center[0] - point[0]).square() + (center[1] - point[1]).square()).sqrt()         };          if norm &lt; max_dist {             close_polygons.push(poly)         }     }      Ok(close_polygons) }  #[pymodule] fn poly_match_rs(_py: Python, m: &amp;PyModule) -> PyResult&lt;()> {     m.add_class::&lt;Polygon>()?;     m.add_function(wrap_pyfunction!(find_close_polygons, m)?)?;     Ok(()) }<\/code><\/pre>\n<p>  <\/p>\n<h2><font color=\"#3AC1EF\">\u258d \u0412\u044b\u0432\u043e\u0434\u044b<\/font><\/h2>\n<p>  <\/p>\n<ul>\n<li>Rust (\u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 pyo3) \u0440\u0430\u0441\u043a\u0440\u044b\u0432\u0430\u0435\u0442 \u0438\u0441\u0442\u0438\u043d\u043d\u0443\u044e \u043d\u0430\u0442\u0438\u0432\u043d\u0443\u044e \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u043f\u043e\u0432\u0441\u0435\u0434\u043d\u0435\u0432\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430 \u043d\u0430 Python \u0441 \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u043c\u0438 \u043a\u043e\u043c\u043f\u0440\u043e\u043c\u0438\u0441\u0441\u0430\u043c\u0438.<\/li>\n<li>Python \u2014 \u043f\u0440\u0435\u0432\u043e\u0441\u0445\u043e\u0434\u043d\u044b\u0439 API \u0434\u043b\u044f \u0438\u0441\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439, \u0430 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0431\u044b\u0441\u0442\u0440\u044b\u0445 \u0441\u0442\u0440\u043e\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0431\u043b\u043e\u043a\u043e\u0432 \u043d\u0430 Rust \u2014 \u044d\u0442\u043e \u0447\u0440\u0435\u0437\u0432\u044b\u0447\u0430\u0439\u043d\u043e \u043c\u043e\u0449\u043d\u043e\u0435 \u0441\u043e\u0447\u0435\u0442\u0430\u043d\u0438\u0435.<\/li>\n<li>\u041f\u0440\u043e\u0444\u0438\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043a\u0440\u0430\u0439\u043d\u0435 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e, \u043e\u043d\u043e \u043c\u043e\u0442\u0438\u0432\u0438\u0440\u0443\u0435\u0442 \u043f\u043e-\u043d\u0430\u0441\u0442\u043e\u044f\u0449\u0435\u043c\u0443 \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u0442\u044c\u0441\u044f \u0441\u043e \u0432\u0441\u0435\u043c, \u0447\u0442\u043e \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0432 \u0432\u0430\u0448\u0435\u043c \u043a\u043e\u0434\u0435.<\/li>\n<\/ul>\n<p>  \u0418 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0435: \u043a\u043e\u043c\u043f\u044c\u044e\u0442\u0435\u0440\u044b <em>\u0431\u0435\u0437\u0443\u043c\u043d\u043e \u0431\u044b\u0441\u0442\u0440\u044b<\/em>. \u041a\u043e\u0433\u0434\u0430 \u0432\u0430\u043c \u0432 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u0440\u0430\u0437 \u043d\u0443\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u0447\u0442\u043e-\u0442\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c, \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0439\u0442\u0435 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u043f\u0440\u043e\u0444\u0438\u043b\u0438\u0440\u043e\u0432\u0449\u0438\u043a, \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u0432\u044b \u043d\u0430\u0443\u0447\u0438\u0442\u0435\u0441\u044c \u0447\u0435\u043c\u0443-\u0442\u043e \u043d\u043e\u0432\u043e\u043c\u0443.<\/p>\n<blockquote><p><b><font color=\"#3AC1EF\"><a href=\"https:\/\/habr.com\/ru\/specials\/731732\/\">\u041f\u043e\u043b-\u043b\u0438\u043c\u043e\u043d\u0430 \u043f\u043e\u0434\u0430\u0440\u043a\u043e\u0432 \u043e\u0442 RUVDS. \u041e\u0442\u0432\u0435\u0447\u0430\u0439 \u043d\u0430 \u0432\u043e\u043f\u0440\u043e\u0441\u044b \u0438 \u043f\u043e\u043b\u0443\u0447\u0430\u0439 \u043f\u0440\u0438\u0437\u044b ?<\/a><\/font><\/b><\/p><\/blockquote>\n<p><a href=\"http:\/\/ruvds.com\/ru-rub?utm_source=habr&amp;utm_medium=article&amp;utm_campaign=perevod&amp;utm_content=uskoryaem_python_v_sto_raz_pri_pomoshhi_menee_chem_sta_strok_na_rust\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/_p\/_h\/lv\/_p_hlvd2tv0cv9tny8tdytzfhje.png\" data-src=\"https:\/\/habrastorage.org\/webt\/_p\/_h\/lv\/_p_hlvd2tv0cv9tny8tdytzfhje.png\"\/><\/a><\/div>\n<\/div>\n<\/div>\n<p><!----><!----><\/div>\n<p><!----><!----><br \/> \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\/732530\/\"> https:\/\/habr.com\/ru\/articles\/732530\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-1\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\"><a href=\"https:\/\/habr.com\/ru\/company\/ruvds\/blog\/732530\/\"><\/p>\n<div style=\"text-align:center;\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/webt\/ve\/wi\/bl\/vewibluh8e0erhybvpmggohupnw.jpeg\" data-src=\"https:\/\/habrastorage.org\/webt\/ve\/wi\/bl\/vewibluh8e0erhybvpmggohupnw.jpeg\" data-blurred=\"true\"\/><\/div>\n<p><\/a><br \/>  \u041e\u0434\u043d\u0430\u0436\u0434\u044b \u043d\u0430 \u0440\u0430\u0431\u043e\u0442\u0435 \u0443 \u043d\u0430\u0441 \u0432\u043e\u0437\u043d\u0438\u043a\u043b\u0430 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 \u0441 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c\u044e \u043e\u0434\u043d\u043e\u0439 \u0438\u0437 \u043d\u0430\u0448\u0438\u0445 \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0445 Python-\u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a.<\/p>\n<p>  \u042d\u0442\u0430 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0444\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u0442 \u0444\u0443\u043d\u0434\u0430\u043c\u0435\u043d\u0442 \u043d\u0430\u0448\u0435\u0433\u043e \u043a\u043e\u043d\u0432\u0435\u0439\u0435\u0440\u0430 3D-\u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438. \u042d\u0442\u043e \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0431\u043e\u043b\u044c\u0448\u0430\u044f \u0438 \u0441\u043b\u043e\u0436\u043d\u0430\u044f \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0449\u0430\u044f NumPy \u0438 \u0434\u0440\u0443\u0433\u0438\u0435 \u043d\u0430\u0443\u0447\u043d\u044b\u0435 \u043f\u0430\u043a\u0435\u0442\u044b Python \u0434\u043b\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0448\u0438\u0440\u043e\u043a\u043e\u0433\u043e \u0441\u043f\u0435\u043a\u0442\u0440\u0430 \u043c\u0430\u0442\u0435\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u0438 \u0433\u0435\u043e\u043c\u0435\u0442\u0440\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0439.<\/p>\n<p>  \u041a\u0440\u043e\u043c\u0435 \u0442\u043e\u0433\u043e, \u043d\u0430\u0448\u0430 \u0441\u0438\u0441\u0442\u0435\u043c\u0430 \u0434\u043e\u043b\u0436\u043d\u0430 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043d\u0430 \u043c\u043e\u0449\u043d\u043e\u0441\u0442\u044f\u0445 \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0438 \u0441 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043d\u044b\u043c\u0438 \u0440\u0435\u0441\u0443\u0440\u0441\u0430\u043c\u0438 CPU, \u0438 \u0445\u043e\u0442\u044f \u043f\u043e\u043d\u0430\u0447\u0430\u043b\u0443 \u043e\u043d\u0430 \u0441\u043f\u0440\u0430\u0432\u043b\u044f\u043b\u0430\u0441\u044c \u0445\u043e\u0440\u043e\u0448\u043e, \u0441 \u0440\u043e\u0441\u0442\u043e\u043c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u0444\u0438\u0437\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u0443 \u043d\u0430\u0441 \u043d\u0430\u0447\u0430\u043b\u0438 \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u0442\u044c \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b, \u0430 \u043d\u0430\u0448\u0430 \u0441\u0438\u0441\u0442\u0435\u043c\u0430 \u0435\u0434\u0432\u0430 \u0432\u044b\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u043b\u0430 \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0443.<\/p>\n<p>  \u041c\u044b \u043f\u0440\u0438\u0448\u043b\u0438 \u043a \u0432\u044b\u0432\u043e\u0434\u0443, \u0447\u0442\u043e \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0443\u0432\u0435\u043b\u0438\u0447\u0438\u0432\u0448\u0435\u0439\u0441\u044f \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u043e\u0439 \u043d\u0443\u0436\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0441\u0438\u0441\u0442\u0435\u043c\u0443, \u043f\u043e \u043a\u0440\u0430\u0439\u043d\u0435\u0439 \u043c\u0435\u0440\u0435, \u0432 \u043f\u044f\u0442\u044c\u0434\u0435\u0441\u044f\u0442 \u0440\u0430\u0437 \u0431\u044b\u0441\u0442\u0440\u0435\u0435, \u0438 \u0440\u0435\u0448\u0438\u043b\u0438, \u0447\u0442\u043e \u043f\u043e\u043c\u043e\u0447\u044c \u0432 \u044d\u0442\u043e\u043c \u043d\u0430\u043c \u043c\u043e\u0436\u0435\u0442 Rust.<\/p>\n<p>  \u0422\u0430\u043a \u043a\u0430\u043a \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438, \u0441 \u043a\u043e\u0442\u043e\u0440\u044b\u043c\u0438 \u043c\u044b \u0441\u0442\u043e\u043b\u043a\u043d\u0443\u043b\u0438\u0441\u044c, \u0432\u0441\u0442\u0440\u0435\u0447\u0430\u044e\u0442\u0441\u044f \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0447\u0430\u0441\u0442\u043e, \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0432\u043e\u0441\u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0438 \u0440\u0435\u0448\u0438\u0442\u044c \u0438\u0445 \u043f\u0440\u044f\u043c\u043e \u0437\u0434\u0435\u0441\u044c, \u0432 (\u043d\u0435 \u0442\u0430\u043a\u043e\u0439 \u0443\u0436 \u043a\u043e\u0440\u043e\u0442\u043a\u043e\u0439) \u0441\u0442\u0430\u0442\u044c\u0435.<\/p>\n<p>  \u0422\u0430\u043a \u0447\u0442\u043e \u0437\u0430\u0432\u0430\u0440\u0438\u0442\u0435 \u0441\u0435\u0431\u0435 \u0447\u0430\u044e (\u0438\u043b\u0438 \u043a\u043e\u0444\u0435) \u0438 \u044f \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443 \u0432\u0430\u043c (\u0430) \u043e \u0441\u0430\u043c\u043e\u0439 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0435 \u0438 (\u0431) \u043e \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u0438\u0442\u0435\u0440\u0430\u0446\u0438\u044f\u0445 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u044b \u0441\u043c\u043e\u0433\u043b\u0438 \u043f\u0440\u0438\u043c\u0435\u043d\u0438\u0442\u044c \u0434\u043b\u044f \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u044d\u0442\u043e\u0439 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b.<\/p>\n<p>  \u0415\u0441\u043b\u0438 \u0432\u044b \u0445\u043e\u0442\u0438\u0442\u0435 \u0441\u0440\u0430\u0437\u0443 \u043f\u0435\u0440\u0435\u0439\u0442\u0438 \u043a \u043f\u043e\u043b\u0443\u0447\u0438\u0432\u0448\u0435\u043c\u0443\u0441\u044f \u043a\u043e\u0434\u0443, \u0442\u043e \u0447\u0438\u0442\u0430\u0439\u0442\u0435 \u0440\u0430\u0437\u0434\u0435\u043b \u00ab\u041f\u043e\u0434\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u0438\u0442\u043e\u0433\u043e\u0432\u00bb.  <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-389291","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/389291","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=389291"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/389291\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=389291"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=389291"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=389291"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}