Kitobni o'qish: «Made at Intel: Сделано в Intel»

Shrift:

В настоящее время Валерий является советником губернатора по развитию ИТ-сектора и отвечает за ИТ-кампус «Неймарк». Ведёт телеграм-канал «Китайский русский» (t.me/russiachinese).

© Издательство «РуДа», 2024

© В. В. Черепенников, 2024

* * *

Валерий Черепенников представляет вашему вниманию честный рассказ о своей более чем двадцатилетней карьере в «Интел», ведущей мировой корпорации в области микроэлектроники. Рекомендую эту книгу всем, кто интересуется разработкой процессоров и соответствующего системного программного обеспечения для них.

Директор Института системного программирования им. В. П. Иванникова РАН академик РАН А. И. Аветисян

Пролог

Время стирает из памяти события, детали, лица. Хорошая новость в том, что плохое мы забываем быстрее, чем хорошее. Плохая в том, что и хорошее мы забываем тоже.

Я рад, что начал писать эту книгу спустя два года после ухода из Intel. Мне хотелось рассказать об уникальной культуре компании и отдать дань уважения людям, у которых я многому научился.

Я еще больше рад, что сумел эту книжку закончить. Желание забить и забросить возникало не однажды и не дважды. Но каждый раз мне удавалось со своей ленью как-то договориться. И всё же с каждой следующей главой становилось все сложнее вытаскивать из своей памяти новые факты и детали. Сейчас мне кажется, что я осветил все значимые истории, которые подарила мне долгая карьера в «Интел», и настало время остановиться.

Эта книжка получилась не совсем такой, как я задумывал ее изначально. И за это я благодарен читателям «Хабра». Поначалу мне думалось, что это будет набор веселых историй, слегка приправленных техническими деталями и философскими рассуждениями. Но потом я заметил, что когда пытался «натягивать на глобус» какие-то концепции – реакция становилась немного унылой. Когда же просто и бесхитростно рассказывал истории из жизни – отклик превосходил мои ожидания. Поэтому я постепенно приходил к всё более натуралистичному стилю изложения. В итоге получилось, что теперь я сам затрудняюсь определить жанровую принадлежность своего творения.

Это точно не набор «корпоративных баек» – в последних главах книжки весёлого очень немного. Тем не менее, это – слово, которое из песни не выкинешь.

Это тем более не «пасквиль бывшего сотрудника». «Интел» дал мне очень многое в жизни, и я всегда буду его любить. Да, косяков и граблей было предостаточно, но по прошествии времени я старался вспоминать о них с улыбкой.

Это точно не автобиография. В книжке я гораздо чаще появляюсь в роли наблюдателя, нежели действующего лица. Возможно, я когда-нибудь за автобиографию и возьмусь, но будем надеяться, что это случится ещё очень и очень нескоро.

И это не трафаретная «бизнес-литература», которая на 90 % состоит из разбора назидательных кейсов с готовыми ответами. Меньше всего мне хотелось заниматься нравоучениями типа «Алеша пошел налево и потерял коня. Добрыня пошел направо и потерял башню (то бишь ладью). А Илья остался на месте и ничего не потерял. Потому что понимал главный принцип: если в большой корпорации можно ничего не делать, то в ней и нужно ничего не делать». Я полагал своих читателей достаточно интеллектуальными и любознательными, чтобы самим во всём разобраться. Свою же задачу видел в том, чтобы погрузить их в проблемную ситуацию и обрисовать действия персонажей. А выводы пусть каждый делает свои собственные.

Наверно, самое близкое определение – это корпоративное бытописание. Мне хотелось донести до вас сложившуюся в light blue уникальную атмосферу. И самый близкий аналог, который я нашел, это книга «Покер лжецов», повествующая о становлении легендарных Salomon Brothers.

Надеюсь, моя история, охватывающая более чем 20-летний период работы в одной из ведущих технологических коропораций мира, покажется вам не менее занимательной.

Architecture and religion1

Я подустал от мрачных текстов и вспомнил о своей давней мечте. За 20 с хвостиком лет работы в «Интел» у меня развеселых историй накопилось на целую книгу. Хотелось в ретроспективе посмотреть на некоторые события, участником которых мне довелось быть. И еще хотелось отдать дань уважения компании и людям, с которыми мне посчастливилось работать. Я уже даже название придумал – Made at Intel. Понятно, что пока я был внутри конторы, речь о публикации этих баек идти не могла. Я сам подшучивал, что для публикации нужно правильно выбрать время. В смысле, сначала уволиться, а потом публиковать, а не быть уволенным вследствие публикации. Однако примерно два года назад я «Интел» покинул, и, казалось бы, меня уже ничего не сдерживало. Но тут как всегда – то перо поломается, то струна порвется, то еще какая беда приключится. К тому же на то, чтобы писать книжку – это же решимости набраться надо… И вот вчера я решил, что большое надо начинать с малого. Буду писать по главке. Так мало-помалу и наберется.

Итак, сегодня вашему вниманию представляется первая глава, в которой эволюция архитектур Intel рассматривается с точки зрения… истории религиозных течений. Да-да, не удивляйтесь, архитектура вычислительных устройств – это одна из самых религиозных вещей. Не думайте, что все решения по Instruction Set Architecture2 принимаются исключительно на основе анализа данных – это совсем не так. Скорее похоже на средневековое государство – тут есть немного бизнеса, побольше политики и очень много религии. Все просто – почти любой эксперимент в этой области растягивается на годы и обходится в миллиарды долларов. Хуже всего, что в процессе дизайна можно давать лишь приблизительные оценки ключевых характеристик – частоты, производительности, энергопотребления, температурной карты. То, как все оно будет на самом деле, становится понятным уже только тогда, когда чип выходит из печки. Да, сейчас в этой области уже накоплен определенный опыт, и наши оценки становятся несколько точнее, но и только. А 20 лет назад этих знаний было куда меньше. И пионеры, подобные «Интел», двигались в темноте на собственный страх и риск. Разумеется, в таких условиях на первый план выходит, кто во что ВЕРИТ. Ну да – еще кто лучше говорить умеет. Лучшие архитекторы приходят из школ с углубленным изучением богословия.

Именно поэтому история эволюция развития архитектурной мысли так странно напоминает историю религий. Разница только в масштабе времени – то, что в религии формируется веками, в дизайне чипов складывается за считанные годы, а иногда даже месяцы. Взять хотя бы школу Бориса Арташесовича Бабаяна (наверно, самую древнюю из известных мне архитектурных школ). Мне трудно впрямую причислить себя к его ученикам, но то, сколько мы общались и сколько идей я от него набрался, наверно, позволяет так говорить. Так вот, там на протяжении 60 лет было все: расколы (наподобие католической и лютеранской церкви), формирование новых течений и, разумеется, идейные конфликты. Существенную роль играл фактор времени. Отколовшиеся недавно признавались «последователями», а долго упорствующие в своих «заблуждениях» – прямыми «еретиками». Много всякого происходило за 60 лет, и я видел из этого лишь малую толику. Поэтому меня подмывает нарисовать полное «генеалогическое древо» этой школы. Когда поеду навестить Арташесовича в следующий раз, надо будет этим заняться. Но давайте вернемся к «Интел». В этой главе я расскажу о трех культах, которые имели все признаки религиозных и формировали историю компании.

Гонка гигагерц

Это течение сформировалось в конце XX – начале XXI века. В основе лежала, в общем-то, простая мысль – при повышении тактовой частоты производительность приложений при прочих равных растет. Не обязательно линейно (обмены с памятью никто не отменял), но растет. Заменяя процессор на новый, пользователь получает ускорение «из коробки». Без всяких мучительных манипуляций с исходным кодом ради распараллеливания и векторизации. Тенденция эта началась еще во времена Pentium III, но полностью развилась уже в Pentium IV. Все было бы прекрасно, но вот только загвоздка в этом самом «при прочих равных». Очевидно, что чем короче такт, тем больше их потребуется для выполнения данной инструкции. Ведь x86 – это все же CISC. И «Интел» задумал поменять архитектуру в угоду частоте. Так родился NetBurst c его гиперпайплайном. Идея в том, чтобы разбить команду на микроинструкции (такой RISC внутри CISC) и запихивать их в огромной длины пайплайн. В Willamette он составлял 20 стадий, а в Prescott – 31, и это не считая декодирования. Суть в том, что эти микроинструкции можно выполнять на гораздо большей частоте, чем настоящие x86 команды. И это неплохо работало на прямых, как палка, кодах и прогретых кэшах. Но стоило поймать промах в кэш, и в пайплайне образовывался баббл (пузырек) – молотилка работала вхолостую. Еще хуже дело обстояло при неправильном предсказании ветвлений. Они не часто (буфер предсказания ветвлений BTB выдавал 94-процентную точность предсказаний), но все же случались. В этом случае цена была астрономической – только для очистки конвейера (flush) могло потребоваться до 100 тактов. А ведь надо было еще снова его загрузить… Тем не менее «Интел» твердо уверовал в парадигму и в начале 2000-x (если мне память не изменяет) провел публичный эксперимент, где P4 работал на частоте около 8 гиг и охлаждался жидким азотом. Это, конечно, вдохновило оверклокеров и заставило серьезно задуматься всех остальных. Ибо гигагерцы – оно, конечно, круто, но жидкий азот – это все-таки жидкий азот…

«Самосожжение» Боба Колвелла

Кульминация, однако, случилась еще раньше. Боб Колвелл (один из самых уважаемых мной дизайнеров) проработал в «Интел» всего пять лет (1995–2000), но сумел оставить в истории компании яркий след. Он был одним из ведущих архитекторов линейки Pentium и, наверно, раньше всех осознал, что «гонка гигагерц» – тупиковый путь. Однако беда была в том, что тогда частота уже превратилась из чисто физического (или инженерного) понятия в предмет новой религии. И обычными средствами набирающую ход лавину было уже не остановить…

В одно прекрасное утро Бобу Колвеллу позвонил тогдашний CEO «Интел» Крейг Баррет. С Крейгом я встречался лично раз пять (больше только с нынешним CEO Пэтом Гелсингером), и он всегда производил впечатление человека исключительно здравомыслящего. Но, видимо, в том момент всеобщий экстаз захватил и его.

– Боб, дружище, нельзя ли поднять частоту еще на 20 %? – «поинтересовался» Крейг.

– Это очень сложно, – ответил Боб. – И более того, контрпродуктивно.

Но тем не менее частота была поднята.

Следующий звонок был таким:

– Боб, дорогой. Нельзя ли добавить еще процентов 15?

– Это почти невозможно и бессмысленно.

– Ну постарайтесь, вы же настоящие гении…

И последний.

– Боб, золотой мой, кровь из носа нужно еще 10 %.

– I deliberately do not agree3, – ответил Боб, повесил трубку и написал заявление «по собственному желанию». Позже он описал это в своей замечательной книге The Pentium Chronicles: The People, Passion, and Politics Behind Intel’s Landmark Chips4.

Дальнейшее развитие

Но «Интел» не был бы «Интелом», если бы так легко отказывался от своих убеждений. NetBurst вышел на рынок и столкнулся там с платформой AMD Opteron, которая мало того что имела существенно более короткий конвейер, так еще и обладала встроенным контроллером памяти. В то время как интеловские платформы все еще использовали технологию North Bridge. На меня самое большое впечатление произвел следующий эпизод. Мы как-то попробовали запустить Linpack на процессоре Irwindale. И не смогли получить более 70 % эффективности. Обычно неприхотливый HPL уперся… в memory bandwidth. Возможно, мы что-то сделали не так, но шок был настолько велик, что мы очень быстро это занятие бросили.

Реальность рынка быстро оказала свое отрезвляющее воздействие. Intel начал стремительно терять долю рынку в пользу AMD. Однако ситуация, как ни странно, имела и положительные моменты для развития софтовой организации в «Интел» (и российской в частности). Контора осознала, что программатуру можно использовать для того чтобы прикрыть недостатки архитектуры. Нас бросили «на фронт», чтобы «распрямлять» коды (уменьшать количество ветвлений) и по возможности уменьшать зависимость от memory bandwidth. В «Интел» наступил (второй?) «золотой век софта». Затем в 2005 году, как глоток свежего воздуха, появился Merom, разработанный в Israel Design Center (IDC). Архитектура Core имела существенно более короткий конвейер и скорее являлась развитием идей P3. Но окончательно «смутное время» закончилось с выходом Nehalem – серверного чипа с архитектурой Core и интегрированным контроллером памяти. Империя встала с колен и нанесла сокрушительный ответный удар.

Architecture and religion – 2

Linpack как важнейшее из искусств

Второй важнейший «культ», который определял развитие серверной архитектуры на протяжении десятилетий, – это «сакрализация» Linpack. Сам бенчмарк представлен Джеком Донгаррой аж в 1979 году. Но культовым статусом своим он обязан усилиям маркетологов из многих IT-компаний (Intel, AMD, IBM, Nvidia, Fujitsu и т. д.). Linpack имеет массу неоспоримых достоинств.

• Это всего лишь ОДИН тест, в отличие от, скажем, SPEC CPU, где их 40 с хвостиком.

• К тому же (в отличие от SPEC) он совершенно бесплатный.

• Очень легко объяснить, что Linpack делает. Он решает систему линейных алгебраических уравнений с числами двойной точности. Используется метод (P) LU-разложения (Гаусса) с выбором ведущего элемента.

• В качестве результата Linpack выдает ОДНО число – измеренную производительность системы в (гига-, тера-, пета-, экза-) флопах. На основании Linpack строится мировой рейтинг суперкомпьютеров TOP-500 и российский TOP-50. Так же вычисляют эффективность (искушенные люди обращают на нее внимание) – как отношение измеренной производительности к пиковой. Правда, в последнее время само понятие эффективности является несколько «размытым» из-за того, что в процессе исполнения теста тактовая частота может «плавать».

• Linpack идеально параллелится (MPI, OpenMP и вообще что угодно) и векторизуется.

• И, наконец, Linpack обеспечивает практически полную (> 90 %) загрузку вычислительных устройств. В то время как обычные приложения редко показывают больше 20.

И все же Linpack – это всего лишь ОДИН (и к тому же весьма специфичный) тест, и переоценка его роли обходится очень дорого. Тем не менее история показывает, что зачастую так оно и происходило.

Гении Линпака

Несмотря на интенсивный promotion со стороны маркетинга, Linpack не приобрел бы и половины своей популярности, если бы не вклад многих талантливых инженеров. Вслед за Донгаррой, безусловно, надо упомянуть Kazushige Goto. Этот парень – настоящий гений (вот только разговорный английский у него хромает), а его статья Anatomy of High-Performance Matrix Multiplication5 давно стала «настольной книгой» для разработчиков библиотек. Я часто приходил к нему с разными вопросами по Линпаку: «Гото-сан, почему так?» И он обычно начинал свои объяснения фразой: «Ну вот представь, что ты – Linpack. Как бы ты поступил на его месте?» Конечно, я ничего не представлял. Просто сидел и слушал с открытым ртом. Потому что для меня это какой-то запредельный уровень понимания. Велик вклад ребят из интеловских MKL (а Linpack это на 95 % dgemm) и MPI. А также их аналогов для других платформ. Ну и не забуду коллег из Intel Competitive Response Team, в которой я провел восемь лет (2005–2013). В нашу задачу входила поддержка больших тендеров в области High Performance Computing6, а также сопровождение подачи заявок в рейтинг Top-500 Supercomputers для свежепостроенных кластеров на базе процессоров Intel.

Мерило тщеславия

Top-500 – самый престижный мировой рейтинг суперкомпьютеров. Чтобы попасть туда, люди тратят десятки и сотни миллионов долларов. Нужно купить и собрать систему, которая может насчитывать десятки тысяч узлов и сотни тысяч интерконнектов. И когда все это сделано, остается последний (и очень ответственный) штрих – измерить производительность системы с помощью теста Linpack и подать заявку. Задача эта отнюдь нетривиальная – у нас была разработана многошаговая процедура для достижения максимального результата. Но надо понимать, что Linpack – это не только Computer Science7, это еще и игра вероятностей. Продолжительность теста зависит от многих факторов: производительности процессоров, количества памяти на узел, количества MPI-ранков и OMP-тредов (если используется гибридная схема параллелизации) и т. д. Таким образом, время прогона может варьироваться от часа до десяти (а то и больше). А за это время с системой из нескольких тысяч узлов может случиться все что угодно – перегреться один из процессоров, отвалиться интерконнект, «cнести башню» драйверу и т. п. Поэтому мало все сделать правильно – нужно, чтобы тебе еще и немного повезло. И ты не можешь предсказать, когда это случится. Для того чтобы получить хороший результат, может потребоваться несколько сотен экспериментальных и «боевых» прогонов. Поэтому за 3–4 недели до International Supercomputing (июнь) и US Supercomputing (ноябрь) у нас начиналась горячая пора. Работа велась посменно и не прекращалась круглые сутки.

В тот день была моя очередь, и я появился на работе в 8:30. Экстремально рано по своим меркам. В офисе было пусто – график посещения в нашей развеселой лавочке был фривольный, и раньше 10–11 обычно никто не появлялся. Застал я только Серегу Шальнова, который гонял Linpack в ночную смену на немецком кластере.

– Чё как? – осведомился я за текущий статус.

– Ночной ран не выжил, – мрачно откликнулся Шальнов. – Сразу несколько узлов скопытились. Я полночи ковырялся, чтобы их вычислить и удалить из списка.

Потом мы наскоро прикинули «расклад» (параметры Np, P и Q) с учетом изменившегося количества узлов, и в этот момент у Сереги зазвонил телефон. Оказалось, что это Войтек, польский чувачок, который занимался технической поддержкой того кластера, на котором мы гоняли тест. Процесс его настолько захватил, что он приперся на работу даже раньше восьми по своему времени.

– Серега, заряжай! – прокричал Войтек так, что даже мне было слышно.

– Ты куда торопишься? – спросил Шальнов. – Скорее в историю войти?

– Дело не в этом. У нас тут похолодало. У меня в подсобке возле датацентра семь градусов. И если ты сейчас не запустишь Linpack (а тепла в процессе теста выделяется дай Бог), я тут сдохну от холода.

Серега положил трубу, посмотрел на меня уставшими, красными после бессонной ночи глазами и изрек:

– Предназначение Линпака не в том, чтобы быть мерилом человеческого тщеславия. Предназначение Линпака в том, чтобы приближать тепловую смерть Вселенной…

Linpack vs HPCC

Если речь зашла о разных «мерилках», то уместно будет упомянуть о HPCC. Мой товарищ Андрей Нарайкин активно продвигал этот набор бенчей как «альтернативу» Линпаку. Нет, разумеется, HPL в составе High Performance Computing Challenge (HPCC) тоже был. Но кроме этого там присутствовали Stream (вечный «антипод» Линпака), Random Access и FFT (плюс несколько дополнительных). Я тогда стебался в том духе, что «Излюбленное занятие джентльменов – мериться размерами достоинства. А ты хочешь указать им на то, что у достоинства, помимо длины, есть еще и другие тактико-технические характеристики. Например, толщина, коэффициент расширения, угол стояния и т. п.» А теперь, спустя более 15 лет, я понимаю, насколько Андрюха был прав. Если бы джентльмены не зацикливались исключительно на длине достоинства, «Интел» сумел бы впоследствии избежать многих болезненных проблем.

Влияние на архитектуру

Колоссальное (при этом не всегда положительное). Я не знаю другого бенчмарка, который оказал бы сравнимое воздействие на историю вычислительной техники в области HPC. Вторым, наверно, идет SPEC CPU, но разрыв огромен (по вышеперечисленным причинам). По сути, SSE2-SSE4, AVX, AVX2, AVX-512 – это все про Линпак. Я здесь остановлюсь на трех кейсах, которые протекали при моем (прямом или косвенном) участии.

• FMA впервые в истории Intel x86 увидел свет в процессоре Haswell. Fused Multiply-Add – это настолько же естественно, как улыбка младенца. Если ты занимаешься умножением, то сложение можешь получить практически бесплатно. Для целых чисел это очевидно, для чисел с плавающей точкой (IEEE754) чуть сложнее, но ненамного. К тому же, по счастливому стечению обстоятельств, наши алгоритмы (например, Dot Product) устроены так, что количество сложений и умножений примерно одинаково. И когда инициативная группа ребят предложила FMA под лозунгом «Линпак – в двойку!», c ними практически никто не спорил. Не, ну а чего спорить, когда ты получаешь сплошные плюсы без каких-либо серьезных минусов.

• AVX-512. Cледующая попытка удвоения производительности была связана с расширением длины SIMD. И вот тут, как говорится, «нашла коса на камень». Возражения возникли моментально, и сколько мы копий тогда сломали, в 2010-2013-х (примерно), пером не описать…

a. Нет в природе столь длинных векторов, чтобы эта машинка давала какие-то преимущества.

b. Tail processing8. Чем длиннее SIMD, тем большей проблемой становится обработка «хвостов» циклов, не кратных 8 (16, 32 и т. п.) операндам. Частично проблема решается маскированием, но лишь частично.

c. Mы в очередной раз уродуем кодировку команд, вводя расширение EVEX.

d. Bytes/Flop. Это было мое основное возражение. Мы усугубляем извечную проблему баланса между загрузками и числодробильными операциями (отношение stream/linpack). И эту архитектуру становится все тяжелее программировать.

e. Непонятно, насколько хорошо можно реализовать всю эту концепцию с физической точки зрения. Как ни странно, в тот момент «люди с паяльниками» вели себя на удивление тихо. Типа «надо – сделаем». И, как оказалось, напрасно…

И все же сила заклинания «Линпак – в двойку!» оказалась достаточной, чтобы перевесить все эти соображения. AVX-512 появился в Xeon Phi и Хeon (начиная со SkyLake) и сразу столкнулся со сложностями. Выяснилось, что основную роль играет именно последнее возражение. Функционирование AVX-512 приводит к перегреву кристалла, и непонятно, как с этим бороться. Упрощенно ситуацию можно описать так. При задействовании AVX-512 в единицу времени срабатывает очень много транзисторов. И они рассеивают много энергии в виде тепла. И ладно бы нагревание происходило равномерно по площади кристалла. С этим можно бороться – поставить кулер помощнее, подвести жидкостное охлаждение и т. п. Но беда в том, что перегрев происходит локально, и это делает проблему куда более злобной. Поначалу Intel пошел по пути наименьшего сопротивления – просто начал сбрасывать частоту при задействовании AVX-512 (в экстремальном случае чуть ли не на гигагерц). Это серьезно подсаживало производительность системы, но на тот момент представлялось временной мерой. Другой путь состоял в том, чтобы «размазать горячие вычисления» по площади кристалла (ядра). Однако тут возникла другая проблема – с синхронизацией и собиранием результата «в кучу». И она оказалась сложнее, чем представлялось изначально. За восемь лет усилий лучшие умы в области электроники так и не смогли подобраться к решению. То, что «Интел» постепенно отказывается от AVX-512, служит косвенным доказательством. И все же хочу сказать пару слов в защиту наших тогдашних решений. Это сейчас представляется «научно доказанным фактом», что 256 бит – оптимальная длина SIMD. А 10 лет назад это было ни разу не очевидно. Наступать на грабли – удел пионеров.

Xeon Phi явился, наверно апогеем культа Linpack. AVX-512 хотя бы умирает (и не факт, что умрет) мучительной смертью, следуя пожеланиям обычно нордически-сдержанного Линуса Торвальдса. В то время как Xeon Phi так и не сумел толком оторваться от взлетной полосы. Он задумывался как ответ набиравшим силу GPGPU. Концепция была такая: давайте натыкаем кучу слабосильных (в Knights Corner использовалась архитектура Pentium), низкочастотных ядер с «православной» ISA и снабдим их зубодробительной длины SIMD. Все это неплохо работало ровно на одном бенчмарке (угадайте, каком). Как только Xeon Phi сталкивался с критическими участками однопоточного кода (а такими, например, являются огромных размеров «cвитчи» в MPI), он немедленно шел на дно (кстати, ISA тут ни при чем.) Всего этого можно было бы избежать, если б в качестве основного теста был взят не HPL, а хотя бы HPCC. Но увы, случилось так, как случилось…

1.Архитектура и религия (англ.).
2.Архитектура набора команд (англ.). Это те регистры и команды процессора, которые доступны для использования программиста.
3.Я категорически не согласен (англ.).
4.Хроники Pentium: люди, страсть и политика, стоящие за знаковыми чипами Intel (англ.).
5.Анатомия высокопроизводительного умножения матриц (англ.).
6.Высокопроизводительные вычисления (англ.).
7.Компьютерная наука (англ.).
8.Обработка хвоста (англ.). Обработка невекторизуемой части цикла.
Yosh cheklamasi:
16+
Litresda chiqarilgan sana:
01 fevral 2024
Yozilgan sana:
2024
Hajm:
237 Sahifa 46 illyustratsiayalar
ISBN:
978-5-9073552-8-6
Mualliflik huquqi egasi:
Издательство "РуДа"
Yuklab olish formati:
Matn
O'rtacha reyting 4,5, 76 ta baholash asosida
Matn PDF
O'rtacha reyting 0, 0 ta baholash asosida
Matn PDF
O'rtacha reyting 3,3, 4 ta baholash asosida
Matn
O'rtacha reyting 4,9, 24 ta baholash asosida