<?xml version="1.0" encoding="utf-8" ?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:tt="http://teletype.in/" xmlns:opensearch="http://a9.com/-/spec/opensearch/1.1/"><title>Steve O'Neil</title><subtitle>Writer, translator, human.</subtitle><author><name>Steve O'Neil</name></author><id>https://teletype.in/atom/steveon</id><link rel="self" type="application/atom+xml" href="https://teletype.in/atom/steveon?offset=0"></link><link rel="alternate" type="text/html" href="https://teletype.in/@steveon?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=steveon"></link><link rel="next" type="application/rss+xml" href="https://teletype.in/atom/steveon?offset=10"></link><link rel="search" type="application/opensearchdescription+xml" title="Teletype" href="https://teletype.in/opensearch.xml"></link><updated>2026-04-16T10:47:07.337Z</updated><entry><id>steveon:S8CSfpMFF4w</id><link rel="alternate" type="text/html" href="https://teletype.in/@steveon/S8CSfpMFF4w?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=steveon"></link><title>Механика XS</title><published>2021-05-19T08:54:06.090Z</published><updated>2021-05-25T12:07:41.063Z</updated><summary type="html">Original: https://theworld.com/~swmcd/steven/perl/pm/xs/intro/index.html</summary><content type="html">
  &lt;p&gt;Original: &lt;a href=&quot;https://theworld.com/~swmcd/steven/perl/pm/xs/intro/index.html&quot; target=&quot;_blank&quot;&gt;https://theworld.com/~swmcd/steven/perl/pm/xs/intro/index.html&lt;/a&gt;&lt;/p&gt;
  &lt;p&gt;Author: &lt;a href=&quot;https://theworld.com/~swmcd/steven/&quot; target=&quot;_blank&quot;&gt;Steven McDougall&lt;/a&gt;&lt;/p&gt;
  &lt;p&gt;Translated by &lt;a href=&quot;https://www.wowessays.com/&quot; target=&quot;_blank&quot;&gt;Wowessays&lt;/a&gt;&lt;/p&gt;
  &lt;p&gt;&lt;strong&gt;Введение&lt;/strong&gt;&lt;/p&gt;
  &lt;p&gt;Эта статья посвящена XS. В ней объясняется, что это такое, зачем он нужен, как он работает и как его использовать. Она включает в себя полный, рабочий пример модуля XS, а также модуль-заглушку, который вы можете использовать в качестве отправной точки для своего собственного кода. Целью данной статьи является предоставление исходных данных и информации, необходимой для написания собственных модулей XS.&lt;br /&gt;&lt;/p&gt;
  &lt;p&gt;Эта статья состоит из пяти частей:&lt;/p&gt;
  &lt;ul&gt;
    &lt;li&gt;|November| &lt;a href=&quot;https://theworld.com/~swmcd/steven/perl/pm/xs/intro/index.html&quot; target=&quot;_blank&quot;&gt;Introduction&lt;/a&gt;| motivation, definitions, examples|&lt;/li&gt;
    &lt;li&gt;|December| &lt;a href=&quot;https://theworld.com/~swmcd/steven/perl/pm/xs/concepts.html&quot; target=&quot;_blank&quot;&gt;Architecture&lt;/a&gt;| the Perl interpreter, calling conventions, data representation|&lt;/li&gt;
    &lt;li&gt;|January| &lt;a href=&quot;https://theworld.com/~swmcd/steven/perl/pm/xs/tools/index.html&quot; target=&quot;_blank&quot;&gt;Tools&lt;/a&gt;| h2xs, xsubpp, DynaLoader|&lt;/li&gt;
    &lt;li&gt;|February| &lt;a href=&quot;https://theworld.com/~swmcd/steven/perl/pm/xs/modules/modules.html&quot; target=&quot;_blank&quot;&gt;Modules&lt;/a&gt;| Math::Ackermann, Set::Bit|&lt;/li&gt;
    &lt;li&gt;|March| &lt;a href=&quot;https://theworld.com/~swmcd/steven/perl/pm/xs/nw/NW.html&quot; target=&quot;_blank&quot;&gt;Align::NW&lt;/a&gt;| Needleman-Wunsch global optimal sequence alignment|&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p&gt;&lt;/p&gt;
  &lt;h3&gt;&lt;strong&gt;Что это такое&lt;/strong&gt;&lt;/h3&gt;
  &lt;p&gt;XS - это (фонетический?) акроним для eXternal Subroutine, где external означает внешний по отношению к Perl, т.е. написанный на каком-то другом языке, например, C или C++. С помощью XS мы можем вызывать подпрограммы языка C непосредственно из кода Perl, как если бы они были подпрограммами Perl.&lt;/p&gt;
  &lt;p&gt;&lt;br /&gt;В узком смысле XS - это название языка-клея, который используется для определения интерфейсов подпрограмм и преобразования данных, необходимых для вызова языка C из Perl. В более широком смысле, XS включает в себя систему программ и средств, которые работают вместе, чтобы это произошло: &lt;em&gt;h2xs, MakeMaker, xsubpp, DynaLoade&lt;/em&gt;r и сам язык XS. Обо всем этом мы поговорим позже.&lt;/p&gt;
  &lt;h3&gt;&lt;strong&gt;Почему это так&lt;/strong&gt;&lt;/h3&gt;
  &lt;p&gt;Perl - это швейцарская армейская бензопила, но все же есть вещи, которые не следует делать на Perl. Например:&lt;/p&gt;
  &lt;ul&gt;
    &lt;li&gt;очень требовательные к процессору вещи, например, численное интегрирование&lt;/li&gt;
    &lt;li&gt;вещи, требующие много памяти.&lt;/li&gt;
    &lt;li&gt;системное программное обеспечение, например, драйверы устройств&lt;/li&gt;
    &lt;li&gt;вещи, которые уже были написаны на других языках.&lt;br /&gt;&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p&gt;В целом, Perl - это &lt;em&gt;язык прикладного программирования&lt;/em&gt;. Он предоставляет мощные средства, такие как автоматическая типизация данных, автоматическое управление памятью, хэш-таблицы и регулярные выражения. Это позволяет легко собирать приложения, не обращая внимания на каждую мелочь. Компромисс заключается в том, что эти средства требуют значительных затрат во время выполнения.&lt;/p&gt;
  &lt;p&gt;В отличие от них, языки C и C++ являются примерами &lt;em&gt;языков системного программирования&lt;/em&gt;. Они обеспечивают контроль над каждым циклом процессора и каждым байтом, поэтому внутренние циклы могут быть быстрыми, а критические структуры данных - маленькими. Компромисс заключается в том, что вы должны программировать каждый цикл процессора и каждый байт во всей программе: даже те части, которые не привязаны к процессору.&lt;/p&gt;
  &lt;p&gt;XS позволяет нам получить лучшее из обоих миров. С XS мы можем использовать Perl для основной части нашего кода, а C - только для тех частей, которые требуют тонкого контроля над системными ресурсами.&lt;/p&gt;
  &lt;h3&gt;&lt;strong&gt;Дорожная развилка&lt;/strong&gt;&lt;/h3&gt;
  &lt;p&gt;Теперь вам нужно решить, хотите ли вы писать XS или просто хотите выполнить работу.&lt;br /&gt;Если вы хотите просто выполнить работу, подумайте об использовании упрощенного генератора обёрток и интерфейсов (&lt;a href=&quot;http://www.swig.org/&quot; target=&quot;_blank&quot;&gt;SWIG&lt;/a&gt;). SWIG - это инструмент разработки программного обеспечения, который соединяет различные языки прикладного программирования, такие как Perl, Python и Tcl, с различными языками системного программирования, такими как C, C++ и Objective-C.&lt;/p&gt;
  &lt;p&gt;SWIG очень прост в использовании. В самом простом случае вы просто передаете ему свой файл .c, указываете язык приложения, и он делает все остальное. Вот пример, взятый из документации SWIG:&lt;/p&gt;
  &lt;pre&gt;unix&amp;gt; swig -perl5 -module example example.c
unix&amp;gt; gcc -c example.c example_wrap.c
unix&amp;gt; ld -G example.o example_wrap.o -o example.so
unix&amp;gt; perl5.005
use example;
print example::factorial(4), &amp;quot;\n&amp;quot;;
&amp;lt;ctrl-d&amp;gt;
24&lt;/pre&gt;
  &lt;p&gt;Я мог бы написать учебник по SWIG, но это было бы излишне: SWIG уже имеет &lt;a href=&quot;http://www.swig.org/doc.html&quot; target=&quot;_blank&quot;&gt;обширную документацию&lt;/a&gt;. SWIG доступен в Интернете, он бесплатен и работает. Если вы хотите просто выполнить работу, то этот SWIG для вас.&lt;/p&gt;
  &lt;h3&gt;&lt;strong&gt;Изучение XS&lt;/strong&gt;&lt;/h3&gt;
  &lt;p&gt;Если вы хотите писать на XS, вы должны изучить его. Изучить XS очень сложно по двум причинам.&lt;br /&gt;Первая заключается в том, что основные документы по Perl, такие как perlxs и perlguts, молчаливо предполагают, что вы уже понимаете XS. Соответственно, они опускают или замалчивают важные предположения и справочную информацию. Это звучит плохо, но на самом деле это &lt;a href=&quot;https://theworld.com/~swmcd/steven/perl/pm/xs/intro/index.html#common&quot; target=&quot;_blank&quot;&gt;довольно распространено&lt;/a&gt; в мире Unix.&lt;/p&gt;
  &lt;p&gt;Вторая причина заключается в том, что вы не можете выучить XS. Не как таковой. Не сверху вниз. Эта проблема гораздо глубже, чем первая, и она проистекает не из неадекватности документации, а из того, чем XS является и чем не является.&lt;/p&gt;
  &lt;p&gt;Документация Perl называет XS языком, но это не так. XS - это набор макросов. Процессор языка XS - это программа под названием &lt;em&gt;xsubpp&lt;/em&gt;, где pp - &lt;a href=&quot;https://theworld.com/~swmcd/steven/perl/pm/xs/intro/index.html#pp&quot; target=&quot;_blank&quot;&gt;сокращение от PreProcessor&lt;/a&gt;, а PreProcessor - вежливый термин для расширителя макросов. xsubpp расширяет макросы XS в биты кода C, необходимые для соединения интерпретатора Perl с вашими подпрограммами языка C.&lt;/p&gt;
  &lt;p&gt;Поскольку XS не является языком, ему не хватает структуры. В коде на языке Си структура есть, но вы ее не видите, потому что она скрыта за макросами. Это делает практически невозможным изучение XS на его собственных условиях.&lt;/p&gt;
  &lt;p&gt;&lt;strong&gt;Возвращение к основам&lt;/strong&gt;&lt;br /&gt;Чтобы изучить XS, вы должны работать снизу вверх. Вы должны изучить API Perl C. Вы должны понять внутренние структуры данных Perl. Вы должны понять, как работает стек Perl и как подпрограмма на языке C получает к нему доступ. Вы должны понимать, как подпрограммы на языке C подключаются к исполняемому файлу Perl. Вы должны понимать пути данных через модуль DynaLoader, которые связывают имя подпрограммы Perl с точкой входа подпрограммы C.&lt;br /&gt;Как только вы поймете все это, вам не понадобится XS: вы можете писать код непосредственно на Perl C API, и ваш код на C будет компоноваться и выполняться под интерпретатором Perl.&lt;/p&gt;
  &lt;p&gt;Если вы будете писать код непосредственно для Perl C API, вы обнаружите, что это трудно, чревато ошибками, утомительно и повторяется. Вы постоянно пишете одни и те же маленькие кусочки кода для перемещения параметров в стек Perl и обратно; для преобразования данных из внутреннего представления Perl в переменные C; для проверки нулевых указателей и других плохих вещей. Когда вы совершаете ошибку, вы не получаете плохой вывод: у вас падает интерпретатор.&lt;/p&gt;
  &lt;p&gt;&lt;strong&gt;Прозрение&lt;/strong&gt;&lt;br /&gt;В конце концов, вы начинаете понимать, как &lt;a href=&quot;https://theworld.com/~swmcd/steven/perl/pm/xs/intro/index.html#advantage&quot; target=&quot;_blank&quot;&gt;выгодно&lt;/a&gt; обернуть эти маленькие кусочки кода в макросы, чтобы написать их один раз и больше о них не беспокоиться. И что вы знаете, кто-то уже написал несколько макросов для вас; есть даже расширитель макросов под названием &lt;em&gt;xsubpp&lt;/em&gt;.&lt;/p&gt;
  &lt;p&gt;Теперь вы понимаете, что такое XS.&lt;/p&gt;
  &lt;h3&gt;&lt;strong&gt;Достаточно сложная проблема&lt;/strong&gt;&lt;/h3&gt;
  &lt;p&gt;Первое, что вам нужно для написания модуля XS - это программа, которую вы совершенно не можете написать на прямом Perl. Писать на C и XS, когда можно было бы писать на Perl, было бы вопиющим неумением быть ленивым.&lt;/p&gt;
  &lt;p&gt;Когда-то моим любимым средством обработки чисел было быстрое преобразование Фурье, но сейчас, когда я думаю о нем, оно кажется мне &lt;a href=&quot;https://theworld.com/~swmcd/steven/perl/pm/xs/intro/index.html#dated&quot; target=&quot;_blank&quot;&gt;устаревшим&lt;/a&gt;. Оно такое классическое, такое линейное, такое старомодное. Кроме того, он работает за O(n*log(n)), что почти не поддается обработке на Perl.&lt;/p&gt;
  &lt;p&gt;Вместо этого я собираюсь написать алгоритм динамического программирования &lt;a href=&quot;https://theworld.com/~swmcd/steven/perl/pm/xs/intro/index.html#NW&quot; target=&quot;_blank&quot;&gt;Нидлмана-Вунша (NW)&lt;/a&gt; для глобального оптимального выравнивания последовательностей. Выравнивание последовательностей - важная проблема в передовой области &lt;a href=&quot;http://www.nhgri.nih.gov/&quot; target=&quot;_blank&quot;&gt;геномики&lt;/a&gt;. Вот вам пару полезных статей:&lt;/p&gt;
  &lt;ul&gt;
    &lt;li&gt;Некоторые &lt;a href=&quot;https://theworld.com/~swmcd/steven/perl/pm/xs/intro/robbins.html&quot; target=&quot;_blank&quot;&gt;мотивы&lt;/a&gt; проблем выравнивания последовательностей&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;https://theworld.com/~swmcd/steven/perl/lib/Game/Stones/Stones.html&quot; target=&quot;_blank&quot;&gt;Краткое описание&lt;/a&gt; динамического программирования в применении к более простой задаче&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;https://www.maths.tcd.ie/~lily/pres2/sld003.htm&quot; target=&quot;_blank&quot;&gt;Описание&lt;/a&gt; NW алгоритма&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;https://theworld.com/~swmcd/steven/perl/pm/xs/intro/align&quot; target=&quot;_blank&quot;&gt;Прямая реализация&lt;/a&gt; алгоритма NW на языке Perl&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p&gt;&lt;br /&gt;Выравнивание последовательностей - это комбинаторная задача, и наивные алгоритмы работают за экспоненциальное время. Алгоритм Нидлмана-Вунша работает за (более или менее) &lt;a href=&quot;https://theworld.com/~swmcd/steven/perl/pm/xs/intro/index.html#order&quot; target=&quot;_blank&quot;&gt;O(n^3)&lt;/a&gt;, что все еще достаточно плохо, чтобы сообщество геномики использовало &lt;a href=&quot;http://www.biocceleration.com/BioXLH-general.html&quot; target=&quot;_blank&quot;&gt;специализированное оборудование&lt;/a&gt; и &lt;a href=&quot;http://www.yeastgenome.org/&quot; target=&quot;_blank&quot;&gt;сетевые базы данных&lt;/a&gt; для выравнивания.&lt;/p&gt;
  &lt;p&gt;В качестве контрольной точки я выровнял 2 последовательности по 200 символов каждая. Это довольно скромная задача по стандартам геномики. Реализация Perl выравнивает их за 200 или 400 секунд. Точное время не имеет значения: это займет больше времени, чем я готов ждать.&lt;/p&gt;
  &lt;p&gt;Шаг O(n^3) в алгоритме NW - это заполнение матрицы оценок; все остальное выполняется за &lt;a href=&quot;https://theworld.com/~swmcd/steven/perl/pm/xs/intro/index.html#linear&quot; target=&quot;_blank&quot;&gt;линейное время&lt;/a&gt;. Я написал программу на языке Си, которая заполняет матрицу оценок.&lt;/p&gt;
  &lt;ul&gt;
    &lt;li&gt;&lt;a href=&quot;https://theworld.com/~swmcd/steven/perl/pm/xs/intro/align.c&quot; target=&quot;_blank&quot;&gt;align.c&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;https://theworld.com/~swmcd/steven/perl/pm/xs/intro/align.h&quot; target=&quot;_blank&quot;&gt;align.h&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;https://theworld.com/~swmcd/steven/perl/pm/xs/intro/main.c&quot; target=&quot;_blank&quot;&gt;main.c&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p&gt;Она выполняет эталонное выравнивание 200x200 за 3 секунды, или примерно в 100 раз быстрее, чем реализация Perl.&lt;/p&gt;
  &lt;p&gt;Я не хочу переписывать остальную часть реализации Perl на C. Части алгоритма сложны, и он в значительной степени полагается на Perl для ведения домашнего хозяйства и управления памятью. Это тот тип кода, который является радостью в Perl и бременем в C.&lt;/p&gt;
  &lt;p&gt;Вместо этого я хочу использовать реализацию C для заполнения матрицы оценок, использовать реализацию Perl для всего остального и использовать XS для обращения от одного к другому. В следующих четырех частях этой статьи мы рассмотрим, как это сделать.&lt;/p&gt;
  &lt;h3&gt;&lt;a href=&quot;https://theworld.com/~swmcd/steven/perl/pm/xs/concepts.html&quot; target=&quot;_blank&quot;&gt;Следующий месяц: Архитектура&lt;/a&gt;&lt;/h3&gt;
  &lt;p&gt;Ранее я утверждал, что XS нужно изучать снизу вверх. Оказалось, что &amp;quot;снизу&amp;quot; - это архитектура фон Неймана для компьютеров с хранимыми программами, и оттуда придется долго подниматься вверх. Вместо того чтобы идти этим путем, мы начнем с самого верха и пройдем путь вниз путем анализа. Это даст нам концепции, необходимые для понимания XS.&lt;/p&gt;
  &lt;p&gt;Нам предстоит изучить много материала, но либо вы понимаете архитектуру, лежащую в основе XS, либо вы хрустящий и хорошо разбираетесь в кетчупе.&lt;/p&gt;
  &lt;h2&gt;ПРИМЕЧАНИЯ&lt;/h2&gt;
  &lt;p&gt;&lt;em&gt;довольно распространенный&lt;/em&gt;&lt;br /&gt;        Я до сих пор помню свое недоумение, когда впервые наткнулся на man-        страницу awk.&lt;br /&gt;&lt;em&gt;pp - сокращение от PreProcessor&lt;/em&gt;&lt;br /&gt;        На самом деле pp - это сокращение от Perl Pseudocode, но звучит неплохо...&lt;br /&gt;&lt;em&gt;преимущество&lt;/em&gt;&lt;br /&gt;        Еще одним преимуществом кодирования в XS является то, что это защищает ваш код от изменений в Perl C API.&lt;br /&gt;&lt;em&gt;датировано&lt;/em&gt;&lt;br /&gt;        1965 год, как это бывает.&lt;br /&gt;        J. В. Кули и Дж. В. Тьюки, &amp;quot;Алгоритм машинного вычисления сложных рядов Фурье&amp;quot;, Математика вычислений, том 19, 1965, стр. 297-301.&lt;br /&gt;&lt;em&gt;Нидлман-Вунш&lt;/em&gt;&lt;br /&gt;        Нидлман, С.Б. и Вунш, К.Д. 1970. &amp;quot;Общий метод, применимый к поиску сходства в аминокислотных последовательностях двух белков&amp;quot; Журнал молекулярной биологии. 48: 443-453.&lt;br /&gt;        &lt;em&gt;См. также&lt;/em&gt;&lt;br /&gt;        Смит, Т.Ф. и Уотерман, М.С. 1981. &amp;quot;Идентификация общих молекулярных подпоследовательностей&amp;quot; Журнал молекулярной биологии. 147: 195-197&lt;br /&gt;&lt;em&gt;O(n^3)&lt;/em&gt;&lt;br /&gt;        O(n^2), если штраф за разрыв-открытие равен нулю&lt;br /&gt;&lt;em&gt;линейное время&lt;/em&gt;&lt;br /&gt;        Алгоритму Смита-Ватермана требуется O(n^2) времени, чтобы найти клетку с наивысшим баллом в матрице.&lt;/p&gt;

</content></entry></feed>