Автор |
Сообщение |
|
|
Заголовок сообщения: |
Re: Трансляторы Си в Форт |
 |
|
Total Vacuum писал(а): Hishnik писал(а): Я пробовал inline, правда, давно было, с соответствующим эффектом относительно процессоров. Выигрыш 1-3 процента, если специально делать тесты с множеством итераций. Простые слова действительно удобно разворачивать прямо в коде. Как сейчас это решается современными ядрами с предсказанием переходов и спекулятивным исполнением - интересный вопрос. Есть соображение, что эффект от разворачивания будет съеден. Точно сейчас не помню (завтра постараюсь прогнать в ПЛИС в двух вариантах), но в Форт-процессорах прирост был раза в 2, если не больше. Возможно, из-за специфики системы команд, когда при коротком машинном слове вызов каждого незаинлайненного слова съедает несколько тактов на call, плюс такт на ret, плюс стек возвратов не резиновый. И почти всегда прошивка с инлайнами не только быстрее, но и меньше. Для широкого машинного слова, вероятно, эффект от инлайна будет небольшим. Более того, под ARM и Thumb у меня иногда даже медленнее прошивка с инлайнами получалась. Под x86 всегда прирост скорости получался от инлайна. Для некоторых моих подопытных время выполнения 16384 итераций Dhrystone (в секундах) и размер прошивки (в нибблах) без инлайнов/с инлайнами: Код: f41 9.396 / 6.226 = 1.51 29519 / 29241 = 1.01 f42 8.889 / 5.571 = 1.60 29498 / 29209 = 1.01 f43 7.560 / 4.987 = 1.52 21535 / 20678 = 1.04 f44 7.021 / 4.471 = 1.57 21216 / 20358 = 1.04 f45 9.897 / 5.976 = 1.66 30116 / 29516 = 1.02 f61 3.717 / 1.858 = 2.00 14436 / 14671 = 0.98 Т.е. прирост скорости раза в 1.5-2, а вот размер прошивки плюс/минус примерно тот же самый.
[quote="Total Vacuum"][quote="Hishnik"]Я пробовал inline, правда, давно было, с соответствующим эффектом относительно процессоров. Выигрыш 1-3 процента, если специально делать тесты с множеством итераций. Простые слова действительно удобно разворачивать прямо в коде. Как сейчас это решается современными ядрами с предсказанием переходов и спекулятивным исполнением - интересный вопрос. Есть соображение, что эффект от разворачивания будет съеден.[/quote]Точно сейчас не помню (завтра постараюсь прогнать в ПЛИС в двух вариантах), но в Форт-процессорах прирост был раза в 2, если не больше. Возможно, из-за специфики системы команд, когда при коротком машинном слове вызов каждого незаинлайненного слова съедает несколько тактов на call, плюс такт на ret, плюс стек возвратов не резиновый. И почти всегда прошивка с инлайнами не только быстрее, но и меньше. Для широкого машинного слова, вероятно, эффект от инлайна будет небольшим. Более того, под ARM и Thumb у меня иногда даже медленнее прошивка с инлайнами получалась. Под x86 всегда прирост скорости получался от инлайна.[/quote] Для некоторых моих подопытных время выполнения 16384 итераций Dhrystone (в секундах) и размер прошивки (в нибблах) без инлайнов/с инлайнами:[code]f41 9.396 / 6.226 = 1.51 29519 / 29241 = 1.01 f42 8.889 / 5.571 = 1.60 29498 / 29209 = 1.01 f43 7.560 / 4.987 = 1.52 21535 / 20678 = 1.04 f44 7.021 / 4.471 = 1.57 21216 / 20358 = 1.04 f45 9.897 / 5.976 = 1.66 30116 / 29516 = 1.02 f61 3.717 / 1.858 = 2.00 14436 / 14671 = 0.98[/code]Т.е. прирост скорости раза в 1.5-2, а вот размер прошивки плюс/минус примерно тот же самый.
|
|
|
 |
Добавлено: Пт мар 21, 2025 02:15 |
|
|
 |
|
|
Заголовок сообщения: |
Re: Трансляторы Си в Форт |
 |
|
Баг или фича? В Dhrystone есть код Код: User_Time = End_Time - Begin_Time ; Он транслируется в Код: User_Time End_Time @ Begin_Time @ - <=> DROP и замечательно работает. Здесь Код: : <=> ( addr val -- val ) OVER ! @ ; Это сишное присваивание, оно делает то же самое, что слово !, только порядок операндов обратный, а кроме того оставляет в стеке значение val. Результат операции присваивания в Си может использоваться в циклах, условных операторах и в выражениях, но чаще всего просто отбрасывается за ненадобностью, что мы и делаем последующей командой DROP. Проверено неоднократно, тесты работают, указатели стека данных/возвратов до/после тестов никуда не уползают (SP@ и RP@). Ну так вот. Попытка сделать простейшую ручную оптимизацию автоматической заменой в коде подстроки Код: <=> DROP на Код: SWAP ! вызывает Exception в SPF, причем конкретно в этой строке. Другие 50 с лишним присваиваний спокойно переживают такую оптимизацию. Кроме того, работают варианты Код: User_Time End_Time @ Begin_Time @ - OVER ! @ DROP User_Time End_Time @ Begin_Time @ - OVER ! DROP End_Time @ Begin_Time @ - User_Time ! End_Time @ Begin_Time @ - User_Time SWAP SWAP ! и даже Код: User_Time End_Time @ Begin_Time @ - SWAP SWAP SWAP ! А вариант Код: User_Time End_Time @ Begin_Time @ - SWAP ! почему-то отказывается. Кто виноват и что делать?  Памагити Были подозрения, что новая реализация clock() портит какие-то регистры, но нет. upd. Перелопатил выхлоп от Dhrystone, повыкидывал почти все, оставил только одну переменную, код выродился в нечто бессмысленное, тем не менее, ничего криминального в таком коде нет: Код: : <=> OVER ! @ ; VARIABLE Done ( var ) 0 Done ! ( init ) : main ( -- ) BEGIN Done @ 0= WHILE ( while ) Done Done @ Done @ - SWAP ! Done 1 <=> DROP REPEAT ( endwhile ) ; ( ret ) main S" done" TYPE Смысл такой: заходим в цикл, делаем одну итерацию, в ходе которой 2 раза пишем в переменную Done, и в идеале должны завершить цикл и вывести "done". Такой код вызывает Exception. Проблема остается, если заменить строку Код: Done 1 <=> DROP на любую из Код: Done 1 OVER ! @ DROP Done 1 OVER ! DROP Но проблема уходит, если заменить ту строку на что-нибудь из Код: Done 1 SWAP ! 1 Done ! и/или заменить Код: Done Done @ Done @ - SWAP ! на Код: Done Done @ Done @ - <=> DROP В других Фортах (Gforth/Irbis/мои самоделки) проблема не наблюдается.
Баг или фича?
В Dhrystone есть код[code]User_Time = End_Time - Begin_Time ;[/code]Он транслируется в[code]User_Time End_Time @ Begin_Time @ - <=> DROP[/code]и замечательно работает. Здесь[code]: <=> ( addr val -- val ) OVER ! @ ;[/code]Это сишное присваивание, оно делает то же самое, что слово !, только порядок операндов обратный, а кроме того оставляет в стеке значение val. Результат операции присваивания в Си может использоваться в циклах, условных операторах и в выражениях, но чаще всего просто отбрасывается за ненадобностью, что мы и делаем последующей командой DROP. Проверено неоднократно, тесты работают, указатели стека данных/возвратов до/после тестов никуда не уползают (SP@ и RP@). Ну так вот. Попытка сделать простейшую ручную оптимизацию автоматической заменой в коде подстроки[code]<=> DROP[/code]на[code]SWAP ![/code]вызывает Exception в SPF, причем конкретно в этой строке. Другие 50 с лишним присваиваний спокойно переживают такую оптимизацию. Кроме того, работают варианты[code]User_Time End_Time @ Begin_Time @ - OVER ! @ DROP User_Time End_Time @ Begin_Time @ - OVER ! DROP End_Time @ Begin_Time @ - User_Time ! End_Time @ Begin_Time @ - User_Time SWAP SWAP ![/code]и даже[code]User_Time End_Time @ Begin_Time @ - SWAP SWAP SWAP ![/code]А вариант[code]User_Time End_Time @ Begin_Time @ - SWAP ![/code]почему-то отказывается. Кто виноват и что делать? :) Памагити :D
Были подозрения, что новая реализация clock() портит какие-то регистры, но нет.
upd. Перелопатил выхлоп от Dhrystone, повыкидывал почти все, оставил только одну переменную, код выродился в нечто бессмысленное, тем не менее, ничего криминального в таком коде нет:[code]: <=> OVER ! @ ; VARIABLE Done ( var ) 0 Done ! ( init ) : main ( -- ) BEGIN Done @ 0= WHILE ( while ) Done Done @ Done @ - SWAP ! Done 1 <=> DROP REPEAT ( endwhile ) ; ( ret ) main S" done" TYPE[/code]Смысл такой: заходим в цикл, делаем одну итерацию, в ходе которой 2 раза пишем в переменную Done, и в идеале должны завершить цикл и вывести "done". Такой код вызывает Exception. Проблема остается, если заменить строку [code]Done 1 <=> DROP[/code]на любую из[code]Done 1 OVER ! @ DROP Done 1 OVER ! DROP[/code]Но проблема уходит, если заменить ту строку на что-нибудь из[code]Done 1 SWAP ! 1 Done ![/code]и/или заменить[code]Done Done @ Done @ - SWAP ![/code]на[code]Done Done @ Done @ - <=> DROP[/code]В других Фортах (Gforth/Irbis/мои самоделки) проблема не наблюдается.
|
|
|
 |
Добавлено: Вт мар 04, 2025 00:46 |
|
|
 |
|
|
Заголовок сообщения: |
Re: Трансляторы Си в Форт |
 |
|
Victor__v писал(а): Реализация инлайна на СПФ весьма странная на самом деле (в свое время знатно прифигел подменам слов >R R> и пр.). Простейшее решение – добавить всем примитивам самопальный флаг инлайна и переписать INTERPRET , чтобы этот флаг учитывался. Благо INTERPRET это слово переопределяемое. Для простейших случаев, когда определение короткое и не содержит строк, пользуюсь хорошим рецептом Код: : << S" LSHIFT" EVALUATE ; IMMEDIATE По большому счету, примерно то же самое, что с моими объявлениями вида :: ... ;
[quote="Victor__v"]Реализация инлайна на СПФ весьма странная на самом деле (в свое время знатно прифигел подменам слов >R R> и пр.). Простейшее решение – добавить всем примитивам самопальный флаг инлайна и переписать INTERPRET , чтобы этот флаг учитывался. Благо INTERPRET это слово переопределяемое.[/quote]Для простейших случаев, когда определение короткое и не содержит строк, пользуюсь хорошим рецептом[code]: << S" LSHIFT" EVALUATE ; IMMEDIATE[/code]По большому счету, примерно то же самое, что с моими объявлениями вида :: ... ;
|
|
|
 |
Добавлено: Пт фев 28, 2025 19:41 |
|
|
 |
|
|
Заголовок сообщения: |
Re: Трансляторы Си в Форт |
 |
|
Ага, ясно теперь. Цитата: This tool chain has reached the stage of proving that a good Forth compiler can be used as a back-end for C. As the usage of C2Forth increases, the amount of carnal knowledge about the target Forth system will decrease. Ultimately the goal is to have output source which is 100% ANS Forth compliant. This is theoretically possible to achieve - just difficult. No attempt has been made to either implement a harness or port the existing one onto anything other than an MPE VFX Forth system. Т.е. в идеале им хотелось бы иметь 100% совместимый ANS-выхлоп, в теории это даже возможно, но слишком муторно, поэтому нафиг надо, так сойдет. В каких-то других Форт-системах, естественно, не проверялось.  Да, если присмотреться, то выхлоп не такой уж жуткий, как показалось поначалу. Тем не менее, не стал бы, вероятнее всего, таким инструментом пользоваться, но не из-за выхлопа, а из-за ограничений самого Си, который там взят за основу (транслятор из LCC переделан и, полагаю, поддерживает стандарт C89): for (int i=0;...;...) нельзя, локальные переменные в середине блока { ... } тоже нельзя и т.д. Два других конкурента все еще не завелись. Один скомпилировался, но не выдает какой-то осмысленный выхлоп, другой пока не скомпилировался.
Ага, ясно теперь. [quote]This tool chain has reached the stage of proving that a good Forth compiler can be used as a back-end for C. As the usage of C2Forth increases, the amount of carnal knowledge about the target Forth system will decrease. Ultimately the goal is to have output source which is 100% ANS Forth compliant. This is theoretically possible to achieve - just difficult. No attempt has been made to either implement a harness or port the existing one onto anything other than an MPE VFX Forth system. [/quote]Т.е. в идеале им хотелось бы иметь 100% совместимый ANS-выхлоп, в теории это даже возможно, но слишком муторно, поэтому нафиг надо, так сойдет. В каких-то других Форт-системах, естественно, не проверялось. :) Да, если присмотреться, то выхлоп не такой уж жуткий, как показалось поначалу. Тем не менее, не стал бы, вероятнее всего, таким инструментом пользоваться, но не из-за выхлопа, а из-за ограничений самого Си, который там взят за основу (транслятор из LCC переделан и, полагаю, поддерживает стандарт C89): for (int i=0;...;...) нельзя, локальные переменные в середине блока { ... } тоже нельзя и т.д.
Два других конкурента все еще не завелись. Один скомпилировался, но не выдает какой-то осмысленный выхлоп, другой пока не скомпилировался.
|
|
|
 |
Добавлено: Пт фев 28, 2025 19:14 |
|
|
 |
|
|
Заголовок сообщения: |
Re: Трансляторы Си в Форт |
 |
|
Total Vacuum писал(а): Смысл в том, что для SPF получается целый пласт слов-прокладок (для MOD, AND, XOR и т.д. и т.п.), тело которых состоит ровно из одного слова, получается лишний слой абстракций. И понятно, что на производительность эти прокладки влияют не лучшим образом. Это не камень в огород SPF, но, к сожалению, не нашел какого-то простого способа объявить в SPF инлайн-слово из коробки (пользуюсь только одним файлом spf4.exe, который валяется тут же в папке с проектом, все прочие библиотеки и древо каталогов с собой не таскаю). И то же самое касается ассемблерных вставок. Если в условном SPF для этого надо подключать с десяток библиотек, то "не очень-то и хотелось". А мне нравится так: Код: :: inc `inc eax` ; Из коробки  Реализация инлайна на СПФ весьма странная на самом деле (в свое время знатно прифигел подменам слов >R R> и пр.). Простейшее решение – добавить всем примитивам самопальный флаг инлайна и переписать INTERPRET , чтобы этот флаг учитывался. Благо INTERPRET это слово переопределяемое.
[quote="Total Vacuum"]Смысл в том, что для SPF получается целый пласт слов-прокладок (для MOD, AND, XOR и т.д. и т.п.), тело которых состоит ровно из одного слова, получается лишний слой абстракций. И понятно, что на производительность эти прокладки влияют не лучшим образом. Это не камень в огород SPF, но, к сожалению, не нашел какого-то простого способа объявить в SPF инлайн-слово из коробки (пользуюсь только одним файлом spf4.exe, который валяется тут же в папке с проектом, все прочие библиотеки и древо каталогов с собой не таскаю). И то же самое касается ассемблерных вставок. Если в условном SPF для этого надо подключать с десяток библиотек, то "не очень-то и хотелось". А мне нравится так:[code]:: inc `inc eax` ;[/code]Из коробки :)[/quote]
Реализация инлайна на СПФ весьма странная на самом деле (в свое время знатно прифигел подменам слов >R R> и пр.). Простейшее решение – добавить всем примитивам самопальный флаг инлайна и переписать INTERPRET , чтобы этот флаг учитывался. Благо INTERPRET это слово переопределяемое.
|
|
|
 |
Добавлено: Вт фев 25, 2025 10:11 |
|
|
 |
|
|
Заголовок сообщения: |
Re: Трансляторы Си в Форт |
 |
|
Господа гусары, простите великодушно, но это какой-то лютый трэш  В c2forth от MPE тесты лежат в папке TESTS, для перекомпиляции теста (например, vartest.c) надо выполнить Код: make.bat vartest Расширение .c не указывать. Препроцессор немного странный, после строки с #include обязательно требует перевод строки 0x0A или 0x0D 0x0A. А у меня в некоторых исходниках просто 0x0D используются в качестве перевода строки, какой редактор поставил, такой и стоит, даже не задумывался как-то. Долго не мог понять, чего он от меня хочет. А еще в обязательном порядке требуется перевод строки после последней скобочки } в конце программы. Ну да ладно, это мелочи. Например, vartest.c (пустые строки поубирал) Код: #include <stdio.h> #include <stdarg.h> int add( int n, ... ) { int i,j; va_list ap; va_start(ap,n); for ( i=0,j=0 ; i<n ; i++ ) j += va_arg(ap,int); va_end(ap); return j; } static int tot; void main( void ) { tot = add(5,1,2,3,4,5); printf("Total is %d\n",tot); } транслируется в Код: PUBLIC _add FLABEL _add :NONAME { $arg0 | $loc[ 36 ] -- } depth $loc[ 32 + ! CompileCall _VM_va_depth $loc[ 12 + ! $loc[ 12 + @ $loc[ 24 + ! #0 $loc[ 28 + ! #0 $loc[ 20 + ! #0 $loc[ 16 + ! CompileBranch @6 LABEL @3 CompileCall _VM_depth $loc[ 8 + ! $loc[ 28 + @ $loc[ 4 + ! $loc[ 4 + @ #1 + $loc[ 28 + ! $loc[ 8 + @ $loc[ 24 + @ - $loc[ 4 + @ + CompileCall _VM_pick $loc[ 0 + ! $loc[ 0 + @ $loc[ 16 + +! LABEL @4 #1 $loc[ 20 + +! LABEL @6 $loc[ 20 + @ addr $arg0 @ < CompileCondBranch @3 #0 $loc[ 28 + ! $loc[ 16 + @ LABEL @1 ; drop PUBLIC _main FLABEL _main :NONAME { | $loc[ 4 ] -- } #5 #4 #3 #2 #1 #5 CompileCall _add nip nip nip nip nip $loc[ 0 + ! $loc[ 0 + @ CompileAddrLit _tot #0 ! CompileAddrLit _tot #0 @ CompileAddrLit @14 #0 CompileCall _printf drop drop LABEL @13 ; drop LABEL _tot #4 allot&erase EXTERN _VM_pick EXTERN _VM_va_depth EXTERN _VM_depth EXTERN _putchar EXTERN _getchar EXTERN _fprintf EXTERN _printf EXTERN _sprintf EXTERN _puts EXTERN _stdout EXTERN _stderr LABEL @14 $54 c, $6F c, $74 c, $61 c, $6C c, $20 c, $69 c, $73 c, $20 c, $25 c, $64 c, $0A c, $00 c, А простой факториал Код: #include <stdio.h> int fac ( char n ) { return n ? n * fac ( n - 1 ) : 1 ; } int n = 9 ; void main ( ) { while ( n = n - 1 ) { printf ( "%i" , fac ( n ) ) ; printf ( "\n" ) ; } } превращается в такое: Код: PUBLIC _fac FLABEL _fac :NONAME { $arg0 | $loc[ 12 ] -- } addr $arg0 @ addr $arg0 c! addr $arg0 c@s $loc[ 4 + ! $loc[ 4 + @ #0 = CompileCondBranch @3 $loc[ 4 + @ #1 - char>cell CompileCall _fac $loc[ 0 + ! $loc[ 4 + @ $loc[ 0 + @ * $loc[ 8 + ! CompileBranch @4 LABEL @3 #1 $loc[ 8 + ! LABEL @4 $loc[ 8 + @ LABEL @1 ; drop PUBLIC _n LABEL _n 9 , PUBLIC _main FLABEL _main :NONAME { | $loc[ 4 ] -- } CompileBranch @9 LABEL @8 CompileAddrLit _n #0 @ char>cell CompileCall _fac $loc[ 0 + ! $loc[ 0 + @ CompileAddrLit @11 #0 CompileCall _printf drop drop CompileAddrLit @12 #0 CompileCall _printf drop LABEL @9 CompileAddrLit _n #0 @ #1 - $loc[ 0 + ! $loc[ 0 + @ CompileAddrLit _n #0 ! $loc[ 0 + @ #0 <> CompileCondBranch @8 LABEL @7 ; drop EXTERN _putchar EXTERN _getchar EXTERN _fprintf EXTERN _printf EXTERN _sprintf EXTERN _puts EXTERN _stdout EXTERN _stderr LABEL @12 $0A c, $00 c, LABEL @11 $25 c, $69 c, $00 c, Если это и Форт, то какой-то очень уж странный, да, знакомые слова иногда встречаются, но больше похоже на какую-то виртуальную машину или даже ассемблер, особенно из-за LABEL @9 и CompileBranch @9. Для сравнения, у меня выхлоп для таких же тестов: Код: : add <enter> ( n ... -- n ) 4 <l> 0 <=> DROP <bp> @ 0 <=> DROP 1 0 DO BEGIN <bp> @ @ 1 PICK 2 + PICK <<> WHILE ( for ) 4 <l> <bp> @ @ 2 PICK SWAP - 1 + PICK <+=> DROP <bp> @ <i++> DROP REPEAT LOOP ( endfor ) 4 <l> @ <vafuncleave> NIP <leave> EXIT ( ret ) <leave> ; ( ret ) 1 <var> tot ( var ) : main <enter> ( -- ) tot 5 1 2 3 4 5 5 add <=> DROP S" Total is %i\n " <asciiz> tot @ 1 printf <leave> ; ( ret ) <locals> main и Код: : fac <enter> ( n -- n ) DUP IF DUP OVER 1 - RECURSE * ELSE 1 THEN NIP <leave> EXIT ( ret ) <leave> ; ( ret ) 1 <var> n ( var ) 9 n ! ( init ) : main <enter> ( -- ) 1 0 DO BEGIN n n @ 1 - <=> WHILE ( while ) n @ fac printn 10 printc REPEAT LOOP ( endwhile ) <leave> ; ( ret ) main В основном слова известные, а реализация всех неизвестных в треугольных скобочках собраны в одном файле c.f. Ну да, есть лишние команды, если смотреть на код, но не думаю, что он окажется сильно медленнее того, что выше c2forth накомпилировал. А если комментариями пометить локальные переменные и аргументы функций и пробелами глубину вложенности обозначить, то код вообще читаемым станет. Такие дела...
Господа гусары, простите великодушно, но это какой-то лютый трэш :) В c2forth от MPE тесты лежат в папке TESTS, для перекомпиляции теста (например, vartest.c) надо выполнить[code]make.bat vartest[/code]Расширение .c не указывать. Препроцессор немного странный, после строки с #include обязательно требует перевод строки 0x0A или 0x0D 0x0A. А у меня в некоторых исходниках просто 0x0D используются в качестве перевода строки, какой редактор поставил, такой и стоит, даже не задумывался как-то. Долго не мог понять, чего он от меня хочет. А еще в обязательном порядке требуется перевод строки после последней скобочки } в конце программы. Ну да ладно, это мелочи. Например, vartest.c (пустые строки поубирал)[code]#include <stdio.h> #include <stdarg.h> int add( int n, ... ) { int i,j; va_list ap; va_start(ap,n); for ( i=0,j=0 ; i<n ; i++ ) j += va_arg(ap,int); va_end(ap); return j; } static int tot; void main( void ) { tot = add(5,1,2,3,4,5); printf("Total is %d\n",tot); }[/code]транслируется в[code]PUBLIC _add FLABEL _add :NONAME { $arg0 | $loc[ 36 ] -- } depth $loc[ 32 + ! CompileCall _VM_va_depth $loc[ 12 + ! $loc[ 12 + @ $loc[ 24 + ! #0 $loc[ 28 + ! #0 $loc[ 20 + ! #0 $loc[ 16 + ! CompileBranch @6 LABEL @3 CompileCall _VM_depth $loc[ 8 + ! $loc[ 28 + @ $loc[ 4 + ! $loc[ 4 + @ #1 + $loc[ 28 + ! $loc[ 8 + @ $loc[ 24 + @ - $loc[ 4 + @ + CompileCall _VM_pick $loc[ 0 + ! $loc[ 0 + @ $loc[ 16 + +! LABEL @4 #1 $loc[ 20 + +! LABEL @6 $loc[ 20 + @ addr $arg0 @ < CompileCondBranch @3 #0 $loc[ 28 + ! $loc[ 16 + @ LABEL @1 ; drop PUBLIC _main FLABEL _main :NONAME { | $loc[ 4 ] -- } #5 #4 #3 #2 #1 #5 CompileCall _add nip nip nip nip nip $loc[ 0 + ! $loc[ 0 + @ CompileAddrLit _tot #0 ! CompileAddrLit _tot #0 @ CompileAddrLit @14 #0 CompileCall _printf drop drop LABEL @13 ; drop LABEL _tot #4 allot&erase EXTERN _VM_pick EXTERN _VM_va_depth EXTERN _VM_depth EXTERN _putchar EXTERN _getchar EXTERN _fprintf EXTERN _printf EXTERN _sprintf EXTERN _puts EXTERN _stdout EXTERN _stderr LABEL @14 $54 c, $6F c, $74 c, $61 c, $6C c, $20 c, $69 c, $73 c, $20 c, $25 c, $64 c, $0A c, $00 c,[/code]А простой факториал[code]#include <stdio.h> int fac ( char n ) { return n ? n * fac ( n - 1 ) : 1 ; } int n = 9 ; void main ( ) { while ( n = n - 1 ) { printf ( "%i" , fac ( n ) ) ; printf ( "\n" ) ; } }[/code]превращается в такое:[code]PUBLIC _fac FLABEL _fac :NONAME { $arg0 | $loc[ 12 ] -- } addr $arg0 @ addr $arg0 c! addr $arg0 c@s $loc[ 4 + ! $loc[ 4 + @ #0 = CompileCondBranch @3 $loc[ 4 + @ #1 - char>cell CompileCall _fac $loc[ 0 + ! $loc[ 4 + @ $loc[ 0 + @ * $loc[ 8 + ! CompileBranch @4 LABEL @3 #1 $loc[ 8 + ! LABEL @4 $loc[ 8 + @ LABEL @1 ; drop PUBLIC _n LABEL _n 9 , PUBLIC _main FLABEL _main :NONAME { | $loc[ 4 ] -- } CompileBranch @9 LABEL @8 CompileAddrLit _n #0 @ char>cell CompileCall _fac $loc[ 0 + ! $loc[ 0 + @ CompileAddrLit @11 #0 CompileCall _printf drop drop CompileAddrLit @12 #0 CompileCall _printf drop LABEL @9 CompileAddrLit _n #0 @ #1 - $loc[ 0 + ! $loc[ 0 + @ CompileAddrLit _n #0 ! $loc[ 0 + @ #0 <> CompileCondBranch @8 LABEL @7 ; drop EXTERN _putchar EXTERN _getchar EXTERN _fprintf EXTERN _printf EXTERN _sprintf EXTERN _puts EXTERN _stdout EXTERN _stderr LABEL @12 $0A c, $00 c, LABEL @11 $25 c, $69 c, $00 c,[/code]Если это и Форт, то какой-то очень уж странный, да, знакомые слова иногда встречаются, но больше похоже на какую-то виртуальную машину или даже ассемблер, особенно из-за LABEL @9 и CompileBranch @9. Для сравнения, у меня выхлоп для таких же тестов:[code]: add <enter> ( n ... -- n ) 4 <l> 0 <=> DROP <bp> @ 0 <=> DROP 1 0 DO BEGIN <bp> @ @ 1 PICK 2 + PICK <<> WHILE ( for ) 4 <l> <bp> @ @ 2 PICK SWAP - 1 + PICK <+=> DROP <bp> @ <i++> DROP REPEAT LOOP ( endfor ) 4 <l> @ <vafuncleave> NIP <leave> EXIT ( ret ) <leave> ; ( ret ) 1 <var> tot ( var ) : main <enter> ( -- ) tot 5 1 2 3 4 5 5 add <=> DROP S" Total is %i\n " <asciiz> tot @ 1 printf <leave> ; ( ret ) <locals> main[/code]и[code]: fac <enter> ( n -- n ) DUP IF DUP OVER 1 - RECURSE * ELSE 1 THEN NIP <leave> EXIT ( ret ) <leave> ; ( ret ) 1 <var> n ( var ) 9 n ! ( init ) : main <enter> ( -- ) 1 0 DO BEGIN n n @ 1 - <=> WHILE ( while ) n @ fac printn 10 printc REPEAT LOOP ( endwhile ) <leave> ; ( ret ) main[/code]В основном слова известные, а реализация всех неизвестных в треугольных скобочках собраны в одном файле c.f. Ну да, есть лишние команды, если смотреть на код, но не думаю, что он окажется сильно медленнее того, что выше c2forth накомпилировал. А если комментариями пометить локальные переменные и аргументы функций и пробелами глубину вложенности обозначить, то код вообще читаемым станет. Такие дела...
|
|
|
 |
Добавлено: Пн фев 24, 2025 02:40 |
|
|
 |
|
|
Заголовок сообщения: |
Re: Трансляторы Си в Форт |
 |
|
А, в форт-процессорах должен быть существенный эффект. Действительно, call - это еще и литерал, и тут важно его эффективно задавать в системе команд. Так что пара call/ret будет заметна по тактам, что усугубится более короткими (в тактах) словами форт-процессора.
А, в форт-процессорах должен быть существенный эффект. Действительно, call - это еще и литерал, и тут важно его эффективно задавать в системе команд. Так что пара call/ret будет заметна по тактам, что усугубится более короткими (в тактах) словами форт-процессора.
|
|
|
 |
Добавлено: Пн фев 24, 2025 01:29 |
|
|
 |
|
|
Заголовок сообщения: |
Re: Трансляторы Си в Форт |
 |
|
Hishnik писал(а): Я пробовал inline, правда, давно было, с соответствующим эффектом относительно процессоров. Выигрыш 1-3 процента, если специально делать тесты с множеством итераций. Простые слова действительно удобно разворачивать прямо в коде. Как сейчас это решается современными ядрами с предсказанием переходов и спекулятивным исполнением - интересный вопрос. Есть соображение, что эффект от разворачивания будет съеден. Точно сейчас не помню (завтра постараюсь прогнать в ПЛИС в двух вариантах), но в Форт-процессорах прирост был раза в 2, если не больше. Возможно, из-за специфики системы команд, когда при коротком машинном слове вызов каждого незаинлайненного слова съедает несколько тактов на call, плюс такт на ret, плюс стек возвратов не резиновый. И почти всегда прошивка с инлайнами не только быстрее, но и меньше. Для широкого машинного слова, вероятно, эффект от инлайна будет небольшим. Более того, под ARM и Thumb у меня иногда даже медленнее прошивка с инлайнами получалась. Под x86 всегда прирост скорости получался от инлайна.
[quote="Hishnik"]Я пробовал inline, правда, давно было, с соответствующим эффектом относительно процессоров. Выигрыш 1-3 процента, если специально делать тесты с множеством итераций. Простые слова действительно удобно разворачивать прямо в коде. Как сейчас это решается современными ядрами с предсказанием переходов и спекулятивным исполнением - интересный вопрос. Есть соображение, что эффект от разворачивания будет съеден.[/quote]Точно сейчас не помню (завтра постараюсь прогнать в ПЛИС в двух вариантах), но в Форт-процессорах прирост был раза в 2, если не больше. Возможно, из-за специфики системы команд, когда при коротком машинном слове вызов каждого незаинлайненного слова съедает несколько тактов на call, плюс такт на ret, плюс стек возвратов не резиновый. И почти всегда прошивка с инлайнами не только быстрее, но и меньше. Для широкого машинного слова, вероятно, эффект от инлайна будет небольшим. Более того, под ARM и Thumb у меня иногда даже медленнее прошивка с инлайнами получалась. Под x86 всегда прирост скорости получался от инлайна.
|
|
|
 |
Добавлено: Пн фев 24, 2025 01:12 |
|
|
 |
|
|
Заголовок сообщения: |
Re: Трансляторы Си в Форт |
 |
|
Я пробовал inline, правда, давно было, с соответствующим эффектом относительно процессоров. Выигрыш 1-3 процента, если специально делать тесты с множеством итераций. Простые слова действительно удобно разворачивать прямо в коде. Как сейчас это решается современными ядрами с предсказанием переходов и спекулятивным исполнением - интересный вопрос. Есть соображение, что эффект от разворачивания будет съеден.
Я пробовал inline, правда, давно было, с соответствующим эффектом относительно процессоров. Выигрыш 1-3 процента, если специально делать тесты с множеством итераций. Простые слова действительно удобно разворачивать прямо в коде. Как сейчас это решается современными ядрами с предсказанием переходов и спекулятивным исполнением - интересный вопрос. Есть соображение, что эффект от разворачивания будет съеден.
|
|
|
 |
Добавлено: Вс фев 23, 2025 22:53 |
|
|
 |
|
|
Заголовок сообщения: |
Re: Трансляторы Си в Форт |
 |
|
 Так, поправка. Умные люди подсказали, что оптимизатор SPF на автопилоте инлайнит простые объявления вида Код: : << LSHIFT ; Так что в этом смысле SPF достаточно хорош. И спасибо ruv за подсказку. Ага, раньше ссылки с сайта MPE на их c2forth были битые, но сегодня обнаружил, что там аж 2 версии, обе скачиваются. Скачал, распаковал, попробую посмотреть. Осталось понять, как там тесты пересобираются. https://www.mpeforth.com/resource-links/downloads/https://www.mpeforth.com/arena/C2ForthKit.120.ziphttps://www.mpeforth.com/arena/c2forth110.zipЕще пара ссылок с Гитхаба, хотя там сразу видно, что что-то не совсем то: https://github.com/yesco/c2forthhttps://github.com/dmedinag/C-to-Forth-compiler
:) Так, поправка. Умные люди подсказали, что оптимизатор SPF на автопилоте инлайнит простые объявления вида[code]: << LSHIFT ;[/code]Так что в этом смысле SPF достаточно хорош. И спасибо [b]ruv[/b] за подсказку. Ага, раньше ссылки с сайта MPE на их c2forth были битые, но сегодня обнаружил, что там аж 2 версии, обе скачиваются. Скачал, распаковал, попробую посмотреть. Осталось понять, как там тесты пересобираются. [url]https://www.mpeforth.com/resource-links/downloads/[/url] [url]https://www.mpeforth.com/arena/C2ForthKit.120.zip[/url] [url]https://www.mpeforth.com/arena/c2forth110.zip[/url] Еще пара ссылок с Гитхаба, хотя там сразу видно, что что-то не совсем то: [url]https://github.com/yesco/c2forth[/url] [url]https://github.com/dmedinag/C-to-Forth-compiler[/url]
|
|
|
 |
Добавлено: Вс фев 23, 2025 21:20 |
|
|
 |
|
|
Заголовок сообщения: |
Re: Трансляторы Си в Форт |
 |
|
Цитата: Эх, заняться бы чем-то более практичным на форте... Это уже было. Увы. Причины не изменились. viewtopic.php?p=49421#p49421viewtopic.php?p=49475#p49475
[quote] Эх, заняться бы чем-то более практичным на форте...[/quote] Это уже было. Увы. Причины не изменились. :( https://fforum.winglion.ru/viewtopic.php?p=49421#p49421 https://fforum.winglion.ru/viewtopic.php?p=49475#p49475
|
|
|
 |
Добавлено: Вс фев 23, 2025 18:47 |
|
|
 |
|
|
Заголовок сообщения: |
Re: Трансляторы Си в Форт |
 |
|
Total Vacuum писал(а): Сейчас циклы и switch дополнительно оборачиваются в конструкцию 1 0 do ... loop, поэтому спокойно транслируем break в leave и выходим из циклов/switch. Но с Irbis почему-то такой трюк не сработал. Поэтому там чуть другая реализация, которая не использует do/loop/leave, но будет работать только со switch, да и то не во всех ситуациях, но для dhrystone этого достаточно. Теперь в Irbis стало даже удобнее в сравнении с SPF/GFORTH. В том смысле, что в нем теперь не требуется обмазывать реализации сишных циклов for/while/do-while дополнительным внешним циклом 1 0 do ... loop для того, чтобы иметь возможность прервать цикл по break. И конструкция switch-case-break-default теперь будет правильно работать в т.ч. для экзотических случаев. Код: extern void CR (); extern void printc (int c); void test (int key) { switch (key) { case 0 : printc('0'); break; case 1 : printc('1'); case 2 : printc('2'); break; case 3 : printc('3'); default : printc('?'); } CR(); } void main() { test(0); test(1); test(2); test(3); test(4); } на выходе даст Код: 0 12 2 3? ? С таймером пока не понял. Сам обработчик запускается, но следующий его запуск производится только после завершения работы длинного по времени слова. В браузерном Форте примерно то же самое: обработчики таймеров и событий не запускаются, если, например, ожидаем нажатия кнопки в цикле внутри какого-то слова. Тут да, определенная специфика есть, нельзя зависать надолго в цикле. Или второй таймер нужен, или хотя бы слово, которое возвращает текущее значение системного времени. Пример с Dhrystone перевыложил: http://totalvacuum.ru/IRBIS/dhry.zipИ с динозавриком тоже: http://totalvacuum.ru/IRBIS/dino.zip
[quote="Total Vacuum"]Сейчас циклы и switch дополнительно оборачиваются в конструкцию 1 0 do ... loop, поэтому спокойно транслируем break в leave и выходим из циклов/switch. Но с Irbis почему-то такой трюк не сработал. Поэтому там чуть другая реализация, которая не использует do/loop/leave, но будет работать только со switch, да и то не во всех ситуациях, но для dhrystone этого достаточно.[/quote]Теперь в Irbis стало даже удобнее в сравнении с SPF/GFORTH. В том смысле, что в нем теперь не требуется обмазывать реализации сишных циклов for/while/do-while дополнительным внешним циклом 1 0 do ... loop для того, чтобы иметь возможность прервать цикл по break. И конструкция switch-case-break-default теперь будет правильно работать в т.ч. для экзотических случаев.[code]extern void CR (); extern void printc (int c); void test (int key) { switch (key) { case 0 : printc('0'); break; case 1 : printc('1'); case 2 : printc('2'); break; case 3 : printc('3'); default : printc('?'); } CR(); } void main() { test(0); test(1); test(2); test(3); test(4); }[/code]на выходе даст[code]0 12 2 3? ?[/code]С таймером пока не понял. Сам обработчик запускается, но следующий его запуск производится только после завершения работы длинного по времени слова. В браузерном Форте примерно то же самое: обработчики таймеров и событий не запускаются, если, например, ожидаем нажатия кнопки в цикле внутри какого-то слова. Тут да, определенная специфика есть, нельзя зависать надолго в цикле. Или второй таймер нужен, или хотя бы слово, которое возвращает текущее значение системного времени. Пример с Dhrystone перевыложил: [url]http://totalvacuum.ru/IRBIS/dhry.zip[/url] И с динозавриком тоже: [url]http://totalvacuum.ru/IRBIS/dino.zip[/url]
|
|
|
 |
Добавлено: Сб фев 22, 2025 19:24 |
|
|
 |
|
|
Заголовок сообщения: |
Re: Трансляторы Си в Форт |
 |
|
Victor__v писал(а): В чём конкретно затык? Может смогу помочь. Да это скорее не "затык", а "хотелка". Допустим, сишное выражение Код: a<<2 моим транслятором превращается в Код: a @ 2 << << - это LSHIFT в терминах SPF, для нее в файле c.f делаю слово-прокладку Код: : << LSHIFT ; Так вот. В моих самодельных Фортах из коробки обычно есть возможность сразу делать слова, которые инлайнятся: Код: : abc ... ; \ обычное слово \ :: abc ... ; \ inline-слово \ : abc ... ; inline \ inline-слово (устаревший вариант) \ Если быть точным, мои Форты воспринимают :: как начало объявляения слова, и те, которые умеют инлайнить - инлайнят, а те, которые не умеют - просто делают обычное определение. И в ситуации с LSHIFT я тупо всегда делаю Код: :: << LSHIFT ; И если Форт-транслятор умеет инлайнить, он заинлайнит, не умеет - сделает обычное слово. Не суть. Смысл в том, что для SPF получается целый пласт слов-прокладок (для MOD, AND, XOR и т.д. и т.п.), тело которых состоит ровно из одного слова, получается лишний слой абстракций. И понятно, что на производительность эти прокладки влияют не лучшим образом. Это не камень в огород SPF, но, к сожалению, не нашел какого-то простого способа объявить в SPF инлайн-слово из коробки (пользуюсь только одним файлом spf4.exe, который валяется тут же в папке с проектом, все прочие библиотеки и древо каталогов с собой не таскаю). А делать отдельный выхлоп << для моих Фортов и LSHIFT для SPF, естественно, сейчас не буду. Вот когда будет готова окончательная версия транслятора Си-в-мой-Форт, тогда можно будет пройтись разок по коду и сделать такие замены в ручном режима, но сейчас точно не стану этим заниматься. И то же самое касается ассемблерных вставок. Если в условном SPF для этого надо подключать с десяток библиотек, то "не очень-то и хотелось". А мне нравится так: Код: :: inc `inc eax` ; Из коробки 
[quote="Victor__v"]В чём конкретно затык? Может смогу помочь.[/quote]Да это скорее не "затык", а "хотелка". Допустим, сишное выражение [code]a<<2[/code]моим транслятором превращается в[code]a @ 2 <<[/code]<< - это LSHIFT в терминах SPF, для нее в файле c.f делаю слово-прокладку[code]: << LSHIFT ;[/code]Так вот. В моих самодельных Фортах из коробки обычно есть возможность сразу делать слова, которые инлайнятся:[code]: abc ... ; \ обычное слово \ :: abc ... ; \ inline-слово \ : abc ... ; inline \ inline-слово (устаревший вариант) \[/code]Если быть точным, мои Форты воспринимают :: как начало объявляения слова, и те, которые умеют инлайнить - инлайнят, а те, которые не умеют - просто делают обычное определение. И в ситуации с LSHIFT я тупо всегда делаю[code]:: << LSHIFT ;[/code]И если Форт-транслятор умеет инлайнить, он заинлайнит, не умеет - сделает обычное слово. Не суть. Смысл в том, что для SPF получается целый пласт слов-прокладок (для MOD, AND, XOR и т.д. и т.п.), тело которых состоит ровно из одного слова, получается лишний слой абстракций. И понятно, что на производительность эти прокладки влияют не лучшим образом. Это не камень в огород SPF, но, к сожалению, не нашел какого-то простого способа объявить в SPF инлайн-слово из коробки (пользуюсь только одним файлом spf4.exe, который валяется тут же в папке с проектом, все прочие библиотеки и древо каталогов с собой не таскаю). А делать отдельный выхлоп << для моих Фортов и LSHIFT для SPF, естественно, сейчас не буду. Вот когда будет готова окончательная версия транслятора Си-в-мой-Форт, тогда можно будет пройтись разок по коду и сделать такие замены в ручном режима, но сейчас точно не стану этим заниматься. И то же самое касается ассемблерных вставок. Если в условном SPF для этого надо подключать с десяток библиотек, то "не очень-то и хотелось". А мне нравится так:[code]:: inc `inc eax` ;[/code]Из коробки :)
|
|
|
 |
Добавлено: Сб фев 22, 2025 19:12 |
|
|
 |
|
|
Заголовок сообщения: |
Re: Трансляторы Си в Форт |
 |
|
Цитата: Ху из мистер ВПС? Кто пишет оптимизатор? Да так идиот один. ВПС - Ваш покорный слуга, т. е. я) Цитата: Вот бы еще инлайнить SPF научить, эх... В чём конкретно затык? Может смогу помочь. Цитата: И даже человек, который пишет свой оптимизатор Форта на Форте, может использовать уже скомпилированный Dhrystone для оценки эффективности оптимизаций.  Кстати, а есть ли DLL какая-нибудь, в которой присутствует дизассемблер? Ну чтобы, ему можно было скормить строку и он выдал листинг на асме. Мне бы это очень пригодилось) Хотя можно ещё найти исходники какого-нибудь консольного дизассемблера на Си и транслировать эти исходники в форт. Блин, это придётся со СПФа код портировать
[quote]Ху из мистер ВПС? Кто пишет оптимизатор?[/quote] [s]Да так идиот один.[/s] ВПС - Ваш покорный слуга, т. е. я)
[quote]Вот бы еще инлайнить SPF научить, эх...[/quote] В чём конкретно затык? Может смогу помочь.
[quote]И даже человек, который пишет свой оптимизатор Форта на Форте, может использовать уже скомпилированный Dhrystone для оценки эффективности оптимизаций. :)[/quote] Кстати, а есть ли DLL какая-нибудь, в которой присутствует дизассемблер? Ну чтобы, ему можно было скормить строку и он выдал листинг на асме. Мне бы это очень пригодилось)
Хотя можно ещё найти исходники какого-нибудь консольного дизассемблера на Си и транслировать эти исходники в форт. [s]Блин, это придётся со СПФа код портировать[/s]
|
|
|
 |
Добавлено: Пт фев 21, 2025 15:16 |
|
|
 |
|
|
Заголовок сообщения: |
Re: Трансляторы Си в Форт |
 |
|
Victor__v писал(а): Хех, пока одни пишут трансляторы си в форт, ВПС пишет оптимизатор форта на форте для форта с маш.кодами just for lulz.
Эх, заняться бы чем-то более практичным на форте... Ху из мистер ВПС? Кто пишет оптимизатор? Вообще-то транслятор Си-в-Форт - побочный продукт, лишь ответвление от основного, да и по функционалу чуть беднее на данный момент. А основной - это транслятор из Си в мой микрофорт для моих Форт-процессоров, т.к. скачать Си под них сейчас тупо негде. Си часто нужен потому, что именно на нем и его ближайших родственниках написана основная масса кода в дикой природе. И иногда проще взять что-то готовое, пусть даже медленное и далеко не оптимальное, чтобы продвинуться дальше и пощупать какие-то решения вживую. А в перспективе переписать узкие места на Форте или ассемблере, тогда итоговый результат получится вполне достойным. Несмотря на то, что транслятор пока сырой, им уже вполне можно пользоваться, что я собственно и делаю время от времени. Взять тот же тест Dhrystone, он вполне пригоден для оценки эффективности различных оптимизаций Форт-ядра. Вот сегодня, например, сделал несколько косметических правок для сишных примитивов в файле c.f, в результате связка транслятор Си-в-Форт+SPF4 заметно ускорилась, порой даже в 2 с лишним раза в сравнении со вчерашним результатом, и стала проигрывать компилятору TCC в 3.5-5 раз. А ведь там пока даже ассемблер не задействован, все примитивы на Форте. Естественно, если примитивы из c.f переписать на ассемблере, станет значительно быстрее. Вот бы еще инлайнить SPF научить, эх... Архив перевыложил. Или несколько простых игр из соседней темы. Там тупо взяты сишные исходники от Ардуино или UzeBox и скомпилированы под Форт-процессор. А чтобы просто написать даже такие относительно несложные игры на Форте, придется кучу времени убить. Намного проще уделить немного времени транслятору, чем каждую из этих простых игр на Форте реализовывать. Или, например, беру реализации алгоритмов рисования линий/кругов на Си, не вникая в их потроха компилирую, после чего могу использовать в своих проектах на Форте. И даже человек, который пишет свой оптимизатор Форта на Форте, может использовать уже скомпилированный Dhrystone для оценки эффективности оптимизаций. 
[quote="Victor__v"]Хех, пока одни пишут трансляторы си в форт, ВПС пишет оптимизатор форта на форте для форта с маш.кодами just for lulz.
Эх, заняться бы чем-то более практичным на форте...[/quote] Ху из мистер ВПС? Кто пишет оптимизатор? Вообще-то транслятор Си-в-Форт - побочный продукт, лишь ответвление от основного, да и по функционалу чуть беднее на данный момент. А основной - это транслятор из Си в мой микрофорт для моих Форт-процессоров, т.к. скачать Си под них сейчас тупо негде. Си часто нужен потому, что именно на нем и его ближайших родственниках написана основная масса кода в дикой природе. И иногда проще взять что-то готовое, пусть даже медленное и далеко не оптимальное, чтобы продвинуться дальше и пощупать какие-то решения вживую. А в перспективе переписать узкие места на Форте или ассемблере, тогда итоговый результат получится вполне достойным. Несмотря на то, что транслятор пока сырой, им уже вполне можно пользоваться, что я собственно и делаю время от времени. Взять тот же тест Dhrystone, он вполне пригоден для оценки эффективности различных оптимизаций Форт-ядра. Вот сегодня, например, сделал несколько косметических правок для сишных примитивов в файле c.f, в результате связка транслятор Си-в-Форт+SPF4 заметно ускорилась, порой даже в 2 с лишним раза в сравнении со вчерашним результатом, и стала проигрывать компилятору TCC в 3.5-5 раз. А ведь там пока даже ассемблер не задействован, все примитивы на Форте. Естественно, если примитивы из c.f переписать на ассемблере, станет значительно быстрее. Вот бы еще инлайнить SPF научить, эх... Архив перевыложил. Или несколько простых игр из соседней темы. Там тупо взяты сишные исходники от Ардуино или UzeBox и скомпилированы под Форт-процессор. А чтобы просто написать даже такие относительно несложные игры на Форте, придется кучу времени убить. Намного проще уделить немного времени транслятору, чем каждую из этих простых игр на Форте реализовывать. Или, например, беру реализации алгоритмов рисования линий/кругов на Си, не вникая в их потроха компилирую, после чего могу использовать в своих проектах на Форте. И даже человек, который пишет свой оптимизатор Форта на Форте, может использовать уже скомпилированный Dhrystone для оценки эффективности оптимизаций. :)
|
|
|
 |
Добавлено: Пт фев 21, 2025 02:13 |
|
|
 |
|