LINUX.ORG.RU

2 маленьких цикла быстрее большого — почему?


0

0

Если коротко, то проблема в том, что один длинный цикл выполняется медленнее, чем несколько аналогичных коротких.

Я транслирую в триады некое арифметическое выражение и потом его считаю. Выражениние большое (гигабайты), но является "механической" суммой тысяч более простых, то есть, просто эти более простые при помощи знака "+" конкатенированы. Пример:

4*x[1]*x[2]- p(3*x[2] + 3*x[1]*x[2] + x[2]*x[3], -4)/648 + l(x[3]*x[5])+(x[1]*x[4] -x[2])/(x[1]*x[3]-125);

просто "механическая" сумма двух коротких:

4*x[1]*x[2]- p(3*x[2] + 3*x[1]*x[2] + x[2]*x[3], -4)/648;

и

l(x[3]*x[5])+(x[1]*x[4] -x[2])/(x[1]*x[3]-125);

(кому интересно, тут x[] -- массив double, p(a,b) -- a в степени b, l(a)-- логарифм, все константы -- double).

При трансляции проводится оптимизация подвыражений, так что, казалось бы, чем выражение длиннее, тем оно должно быстрее считаться, поскольку триад меньше получается. Но это не так, начиная с некоторого момента считается дольше. Например, выражение изначально содержит 644698410 операций, и представлено в виде:

Первый раз 10 файлов размером от 34 MB до полутора GB.

Второй раз 21271 файлов размером от 136 байт до полутора MB.

После оптимизации подвыражений число операций:

Первый раз 27225617

Второй раз 40982442

То есть, во втором случае кол-во требуемых операций в полтора раза больше.

Суммарное время вычисления:

Первый раз 0.3614 секунды

Второй раз 0.1752 секунды

С чем это может быть связано?

★★★★★

Вот кусок кода, который считает выражение --
просто длинный свитч по всем операциям в цикле.

Гда я линейность по размеру задачи теряю?
Может, я что-то тривиально не то со структурами делаю?

Я пробовал вместо char * для операций int использовать, разница минимальная.

Операции -- массив char'ов, сами триады -- массив 
структур triadaddr_t :


typedef struct {
   double *operand1;
   double *operand2;
   double result;
}triadaddr_t;

typedef struct {
   char *operations;
   triadaddr_t *operands;
   long int length;
}triad_t;

static inline double runtriads(triad_t *rt)
{
char *tro=rt->operations;
char *troStop=rt->operations+rt->length;
triadaddr_t *tra=rt->operands;
   for(;tro<troStop;tro++,tra++){
      switch(*tro){
         case O_LOG :
            tra->result = log(*(tra->operand1));
            break;
         case O_POW :
            tra->result = pow(*(tra->operand1),*(tra->operand2));
            break;
         case O_MINUS :
            tra->result = *(tra->operand1) - *(tra->operand2);
            break;
         case O_DIV :
            tra->result = *(tra->operand1) / *(tra->operand2);
            break;
         case O_PLUS :
            tra->result = *(tra->operand1) + *(tra->operand2);
            break;
         case O_MUL :
            tra->result = *(tra->operand1) * *(tra->operand2);
            break;
         . . .
           blah-blah-blah на страницу
      }/*switch(*tro)*/
   }/*for(;tro<troStop;tro++,tra++)*/
   --tra;
   return tra->result;
}

Die-Hard ★★★★★
() автор топика

> С чем это может быть связано?

Кеш процессора?

anonymous
()

Честно говоря не понял, при чём тут циклы, может в первом случае триады содержат простые операции вроде сложения а во втором сложные.

Legioner ★★★★★
()
Ответ на: комментарий от Legioner

> Честно говоря не понял, при чём тут циклы,

Ну, триады же в цикле вычисляются.

Под "большими" и "маленькими" циклами я имел в виду кол-во раз, которое тело цикла выполняется. Тело цикла в обоих случаев одно и то же.

> может в первом случае триады содержат простые операции вроде сложения а во втором сложные.

Это ОДНО И ТО ЖЕ ВЫРАЖЕНИЕ! Просто на куски разбито по-разному: один раз мало, но больших кусков, второй раз -- много маленьких.

Die-Hard ★★★★★
() автор топика
Ответ на: комментарий от Die-Hard

> Это ОДНО И ТО ЖЕ ВЫРАЖЕНИЕ! Просто на куски разбито по-разному: один раз мало, но больших кусков, второй раз -- много маленьких.

Ну тогда прав анонимный брат - кэш. Большое выражение вызывает дребезг, маленькое - нет.

tailgunner ★★★★★
()
Ответ на: комментарий от vasily_pupkin

> Немного не в тему конечно, но разве switch/case в таком случае будет оптимально?

Очень даже в тему, я и спрашиваю! А какие еще мысли есть?

Die-Hard ★★★★★
() автор топика
Ответ на: комментарий от Die-Hard

Однозначная таблица переходов. Ну, т.е. или вырожденная хэш-функция для вычисления суб-блока, или просто массив адресов ф-й перехода, где адрес "ф-ии" - адрес кода обработки "действий". Ф-ии должны быть naked ессн. Скакать конечно будет огого, но в такой кейсовой таблице тоже по идее кал еще тот выходит. В общем и целом - можно померить. Вдруг будет хорошо. Просто если у вас там простыня вниз, то будет однозначно быстрее ^_^

vasily_pupkin ★★★★★
()
Ответ на: комментарий от tailgunner

> Большое выражение вызывает дребезг, маленькое - нет.

Да не должно! Они ж почти линейно вычисляются, "в поряке поступления". Запись вообще строго строго в след. ячейку, а чтение ... Ну, не знаю -- 12 мегабайт второго кыша, все же...

Придумал, заставлю его не оптимизировать подвыражение, если оно оказалось слишком "далеко" -- если вы с анонимусом правы, введение такого параметра должно ускорить, если нет -- замедлить вычисление.

Die-Hard ★★★★★
() автор топика
Ответ на: комментарий от vasily_pupkin

> Однозначная таблица переходов.

А чем она от свитча отличается?

> ...или вырожденная хэш-функция для вычисления суб-блока,

Каждый мой суб-блок -- ОДНА операция над FP, которая, как правило, на второй корке быстрее целочисленных.

> или просто массив адресов ф-й перехода, где адрес "ф-ии" - адрес кода обработки "действий".

Не понял,

Вот у меня есть массив переходов, скажем, для 10 операций, от 0 до 9, jmpAddr[10]. И вот у меня есть операция Op, равная 5. Мои действия?

Die-Hard ★★★★★
() автор топика
Ответ на: комментарий от Die-Hard

> Вычисляемый goto и есть switch()...

Это зависит от настроения компилятора :) Если у тебя GCC, сделай честный вычисляемый goto;

tailgunner ★★★★★
()
Ответ на: комментарий от Die-Hard

> Вот у меня есть массив переходов, скажем, для 10 операций, от 0 до 9, jmpAddr[10]. И вот у меня есть операция Op, равная 5. Мои действия? 

В самом простом случае: jmpAddr[5](first_operand, second_operand); 

Вот пример:

typedef int (* fptr)(int a, int b);

int plus(int a, int b)
{
    return a+b;
}

int minus(int a, int b)
{
    return a-b;
}




int main()
{

    fptr ptrs[2];

    int a = 10;
    int b = 9;

    ptrs[0] = plus;
    ptrs[1] = minus;

    printf("%d op1 %d = %d, %d op2 %d = %d\n", a, b, ptrs[0](a, b), a, b, ptrs[1](a,b));

    return 0;
}

alex@Outcast $ ./a.out
10 op1 9 = 19, 10 op2 9 = 1

Если бы это был MSVS, можно такие функции было бы разместить подряд, сделать __declspec(naked) и не парится. А так рекомендую написать небольшой кодогенератор для asm-кода :)

vasily_pupkin ★★★★★
()
Ответ на: комментарий от tailgunner

> Если у тебя GCC, сделай честный вычисляемый goto;

Попробую. Но мне надо еще, чтобы оно и под виндой работало!

Но к обсуждаемой проблеме это напрямую, все же, не относится...

Die-Hard ★★★★★
() автор топика

>Первый раз 10 файлов размером от 34 MB до полутора GB.

Не связанно ли это с дисковой подсистемой?

wfrr ★★☆
()
Ответ на: комментарий от vasily_pupkin

Гм. Походу gcc 4.3 уже что то адекватное делает (%

alex@Outcast $ cat test2.c
int test(int a)
{
    int res = 0;
    switch (a)
    {
        case 5:
            res = pow(a, 10);
            break;
        case 6:
            res = pow(a, 11);
            break;
        case 7:
            res = pow(a, 12);
            break;

        case 8:
            res = pow(a, 13);
            break;
        case 9:
            res = pow(a, 14);
            break;

        case 10:
            res = pow(a, 15);
            break;


        default:
            res = 1;
            break;
    }
    return res;
}

int main()
{


    return 0;
}

.globl test
        .type   test, @function
test:
        pushl   %ebp
        movl    $1, %eax
        movl    %esp, %ebp
        movl    8(%ebp), %edx
        subl    $5, %edx
        cmpl    $5, %edx
        ja      .L12
        jmp     *.L11(,%edx,4)
        .section        .rodata
        .align 4
        .align 4
.L11:
        .long   .L5
        .long   .L6
        .long   .L10
        .long   .L10
        .long   .L10
        .long   .L10
        .text
        .p2align 4,,7
        .p2align 3
.L10:
        movl    $2147483647, %eax
.L12:
        popl    %ebp
        ret
        .p2align 4,,7
        .p2align 3
.L6:
        movl    $362797056, %eax
        popl    %ebp
        .p2align 4,,6
        .p2align 3
        ret
        .p2align 4,,7
        .p2align 3
.L5:
        movl    $9765625, %eax
        popl    %ebp
        .p2align 4,,4
        .p2align 3
        ret
        .size   test, .-test
        .ident  "GCC: (GNU) 4.3.1"
        .section        .note.GNU-stack,"",@progbits


vasily_pupkin ★★★★★
()
Ответ на: комментарий от vasily_pupkin

Ну, нет, совсем не то! В любом случае это будет несколько целых операций для того, чтобы добраться до кода (сдвиг в jmpAddr, спасение регисторов / восстановление регистров, длинный переход), когда мне надо всего два перехода. У меня же _очень_ короткие операции, они в среднем выполняются быстрее _одной_ операции над целыми!

И naked не спасет: The naked attribute affects only the nature of the compiler's code generation for the function's prolog and epilog sequences. It does not affect the code that is generated for calling such functions.

Впрочем, попробую ради интереса.

> А так рекомендую написать небольшой кодогенератор для asm-кода :)

Оно у меня должно работать и под Линух с Вендой, и на Итанике и на x86-64 :(

Die-Hard ★★★★★
() автор топика
Ответ на: комментарий от vasily_pupkin

> Гм. Походу gcc 4.3 уже что то адекватное делает (%

А я всегда думал, что так оно и есть!

Надо посмотреть на моих версиях....

Die-Hard ★★★★★
() автор топика
Ответ на: комментарий от wfrr

> Не связанно ли это с дисковой подсистемой?

Нет, я замеряю чистое время сотни вычислений и потом эти времена складываю.

И вообще, мы к этому пришли из практических наблюдений: когда много мелких, моя часть ведет себя линейно по размеру входных данных. Но уж очень тормозит на мелких и средних масштабах!

Die-Hard ★★★★★
() автор топика
Ответ на: комментарий от Die-Hard

Действительно, кыш болтается!

> Придумал, заставлю его не оптимизировать подвыражение, если оно оказалось слишком "далеко" -- если вы с анонимусом правы, введение такого параметра должно ускорить, если нет -- замедлить вычисление.

Поставил тупое ограничение: если триада уже была вычислена, но расстояние до нее больше 909200 (от балды число), то она вычисляется заново. В результате кол-во несоптимизированных триад возросло на 11%, но считать оно стало на 11% быстрее!

Die-Hard ★★★★★
() автор топика

Я так понял, ты рассматриваешь 2 варианта.

1. построить дерево триад, соптимизировать, вычислить.

2. поочерёдно для каждого фрагмента дерева триад: построить, соптимизировать, вычислить.

И я так понял, проблема в том, что вычисление в 1-м случае идёт дольше, чем суммарное время вычислений во 2-м, хотя, вроде бы, в 1-м случае за счёт оптимизации вычислений даже должно быть меньше.

Если так, то, вероятно, дело действительно в кеше. В первом случае этап вычисления читает данные из основной памяти (в кэш не влезут). Во втором - на момент начала вычисления каждого фрагмента - в кэше ещё есть данные, которые попали туда в момент построения дерева (либо, если вычисляешь много раз повторно, то с предыдущего вычисления).

А switch/case - у тебя ж число меток определяется кодом, а не деревом триад, тогда и результат должен быть одинаков? Да и трудно представить такой switch/case, таблица переходов которого не влезла бы в кэш :)

PS. Думаю, есть некий оптимальный размер фрагмента, когда он и в любой кэш влазит, и в котором уже есть что соптимизировать.

PPS. проверка идеи делается так: во втором варианте делаешь вычисление дважды и находишь отдельно суммарное время всех первых вычислений и вторых вычислений. Не забудь выключить оптимизацию, а то она решит, что повторно вычислять смысла нет, и даст такой же эффект, как и кэш, только сильнее.

alexsaa
()
Ответ на: комментарий от alexsaa

> Я так понял, ты рассматриваешь 2 варианта. 1... 2... хотя, вроде бы, в 1-м случае за счёт оптимизации вычислений даже должно быть меньше.

Совершенно верно. И дело действительно в кэше -- см. мой пред. пост

> А switch/case - у тебя ж число меток определяется кодом, а не деревом триад, тогда и результат должен быть одинаков?

Конечно! Разговор про switch просто "параллельно" пошел.

> Думаю, есть некий оптимальный размер фрагмента, когда он и в любой кэш влазит, и в котором уже есть что соптимизировать.

Да, я тоже к этому склоняюсь. В принципе, есть еще идеи с расположением адресов повозиться, чтобы кыш поменьше инвалидировать но игра не стОит свеч, наверное, к тому же это может привести к сильному увеличению времени трансляции, что тоже важно. Плюс к тому, эти штуки мы интегрируем, так что все эти куски можно обсчитывать параллельно (а каждое выражение, даже маленькое, после трансляции в триады вычисляется в полутора миллионов точек, и это уже не мелкая операция), что неплохо для лоад балансинга, поскольку мы можем параллелиться на сотни ветвей теперь (мощности для этого есть).

Просто надо было понять, почему мой такой из себя "саблинейный" алгоритм себя ведет "сверхлинейно".

Die-Hard ★★★★★
() автор топика

Зря вы, Die-Hard, не послушались умного совета употребить в этой вашей задаче встроенный Форт. Ваша реализация обречена быть тормозом при любой другой модели вычислений.

anonymous
()
Ответ на: комментарий от anonymous

> Зря вы, Die-Hard, не послушались умного совета употребить в этой вашей задаче встроенный Форт. Ваша реализация обречена быть тормозом при любой другой модели вычислений.

Гы! А почему не Лисп (или Джава) ?

Слова "Ваша реализация обречена быть тормозом при любой другой модели вычислений" содержит имманентное противоречие в силу теоремы Гёделя о неполноте аксиоматики.

:-)

Die-Hard ★★★★★
() автор топика
Ответ на: комментарий от Die-Hard

> Гы! А почему не Лисп (или Джава) ?

Я в той теме уже объяснял, почему. Да вы и сами это в условии задачи сформулировали - компилятор захлебнётся от такого дерева. Тогда как выражение на Форте (ну или любой другой стековой машине) можно формировать с константной по памяти сложностью промежуточных операций.

Кроме того, то, что вы понаписали - это именно тормоз и есть. При реализации на прямом шитом коде (то, что большинство фортов умеет делать) производительность будет близка к Си, и поведение кэша будет гарантированно понятным.

Недофорт же для вашей конкретной задачи сделать можно в 100 строк на ассемблере, если не меньше. Работы на час максимум.

anonymous
()
Ответ на: комментарий от anonymous

> При реализации на прямом шитом коде (то, что большинство фортов умеет делать) производительность будет близка к Си, и поведение кэша будет гарантированно понятным.

??? Вообще-то прямой шитый код должен гарантированно сносить крышу предсказателю переходов, поэтому насчет скорости - ви таки уверены?

anonymous
()
Ответ на: комментарий от anonymous

> Я в той теме уже объяснял, почему.

Можно еще раз (или сослаться слова в той теме)?

> ...компилятор захлебнётся от такого дерева. Тогда как выражение на Форте (ну или любой другой стековой машине) можно формировать с константной по памяти сложностью промежуточных операций.

Немного не улавливаю...

Я формирую триады на стековой машине. С линейным временем (если оптимизацию убрать). При тупой (линейной) оптимизации подвыражений время компиляции остается линейным, у меня слегка выпирает за счет эвристики. Чем мне поможет константная по памяти сложность промежуточных операций?

> При реализации на прямом шитом коде (то, что большинство фортов умеет делать) производительность будет близка к Си,

Можно чуть подробнее? Чем принципиально (в моем случае) шитый код отличается от вычисления триад в цикле?

> и поведение кэша будет гарантированно понятным.

Почему? ИМХО как раз шитый код в моем случае усилит дребезжание кыша...

Die-Hard ★★★★★
() автор топика
Ответ на: комментарий от Die-Hard

Для того, чтобы вычислить выражение, вовсе не обязательно делать запись в память для каждого узла дерева - большинство промежуточных выражений могут оставаться в регистрах fpu. Всё это мог бы сделать обычный компилятор, если бы ты предоставил ему возможность скомпилировать выражение.

А в твоём подходе всё начинается с того, что при *каждой* операции делается 2 чтения и 1 запись в память. И компьютер вынужден в конце концов эти промежуточные результаты записать в основную память, сколько бы там кэша не было и как бы ты не изощрялся в оптимизации попаданий в кэш при чтении. А на самом деле всё это тебе не нужно.

afaik, современный fpu делает простые операции быстрее, чем их может передать основная память.

alexsaa
()
Ответ на: комментарий от alexsaa

> ...вовсе не обязательно делать запись в память для каждого узла дерева ... А в твоём подходе всё начинается с того, что при *каждой* операции делается 2 чтения и 1 запись в память.

Я совершенно отчетливо все это понимаю.

> И компьютер вынужден в конце концов эти промежуточные результаты записать в основную память,

Да, это проблема. Но во многих случаях результаты потом много раз читаются.

> А на самом деле всё это тебе не нужно.

И как это сделать, не прибегая к ручной кодогенерации прямо в память?

Главное же -- лишнее копирование из регистра в память совершенно ничто по сравнениею с оптимизацией подвыражений.

В общем, я осознал, что моя проблема с кышом происходит не столько из чтения, сколько из инвалидации кыша ненужными записями. Но как с этим бороться?

Die-Hard ★★★★★
() автор топика
Ответ на: комментарий от Die-Hard

> А на самом деле всё это тебе не нужно.

В принципе, можно попробовать на выбор спасать результат в локальную переменную (если оно потом не нужно), это должно вписаться в линейность трансляции. Но у меня подозрение, что это будет дольше (одна лишняя целочисленная операция гораздо дольше типичной операции fpu).

Шитый код, конечно, можно попробовать... Но я не потяну, наверное -- оно нужно на кучу платформ. А и так быстро работает, вроде.

Die-Hard ★★★★★
() автор топика

Вообще, всем спасибо -- все замечания и советы были очень конструктивны, будем дальше думать... Пока и так работает, но простор для творчества необозрим. :-) Я это не к тему, чтобы закрыть дискуссию -- просто спасибо всем выступившим говорю.

Die-Hard ★★★★★
() автор топика
Ответ на: комментарий от Die-Hard

Э... Как раз таки триады надо компилировать в оптимизированный native. Шитый код для всего остального мега-выражения.

anonymous
()
Ответ на: комментарий от anonymous

> Как раз таки триады надо компилировать в оптимизированный native.

Как? Прямо в память?

> Шитый код для всего остального мега-выражения.

Компиляция в нейтив невозможна по "техническому заданию" :). В результате шитый код не поимеет преимуществ перед обработкой триад в цикле, только лишние целочисленные операции привнесет.

У меня оптимизация "а-ля Форт" выполняется на уровне триад: все триады сидят в словаре, и лишний раз не вычисляются. Проблема в том, как формализовать "адрес триады" -- перейти к тетрадам? -- глупо, указатель занимает столько же места, что и результат, да еще и операций требует целочисленных.

Я в принципе придумал: буду хранить не шибко нужные результаты в локальном массиве, это ушестерит кол-во арифметических "операций" (и длинну свитча), но скорость трансляции от линейности не уведет. Посмотрим.

Die-Hard ★★★★★
() автор топика
Ответ на: комментарий от tailgunner

2 tailgunner & vasily_pupkin:

>> Вычисляемый goto и есть switch()...

>Это зависит от настроения компилятора :) Если у тебя GCC, сделай честный вычисляемый goto;

Попробовал, сделал "goto по предписанию": сделал таблицы всех меток с помощью оператора "&&" и goto на элемент. Быстрее, действительно -- на 3% :-)

Интересно, что и icc это зажевал.

Кстати, icc у меня стабильно сливает gcc несколько процентов (это на Зеоне-то!).

Die-Hard ★★★★★
() автор топика
Ответ на: комментарий от Die-Hard

> Быстрее, действительно -- на 3% :-)

"В долгой дороге и жук - мясо" (c)

tailgunner ★★★★★
()
Ответ на: комментарий от Die-Hard

> Как? Прямо в память?

А куды ж ещё? Hint: lcc, для ленивых.

> Компиляция в нейтив невозможна по "техническому заданию" :).

???

Она всегда возможна.

anonymous
()
Ответ на: комментарий от Die-Hard

Да, кстати, от свича или вычислимого goto тоже можно избавиться, выдавливая прямо в память прямой шитый код (то есть, jump-ы формировать по заготовленным адресам).

anonymous
()
Ответ на: комментарий от anonymous

>> Компиляция в нейтив невозможна по "техническому заданию" :).

> Она всегда возможна.

Кодогенерить в машинные инструкции я не хочу: мне надо несколько архитектур, оно через два года устареет, появятся новые архитектуры, вставят защиту памяти, итп., и я не хочу потом всю жизнь это поддерживать.

Можно будет попробовать какой-нибудь runtime assembler, типа GNU lightning, но боюсь, они генерят слишком долго и слишком generic код.

Die-Hard ★★★★★
() автор топика
Ответ на: комментарий от anonymous

> выдавливая прямо в память прямой шитый код (то есть, jump-ы формировать по заготовленным адресам).

У меня уже триады готовые, мне jump-ы почти не нужны (с точночтью до if-ов, которые у нас, к сожалению, иногда встречаются), и шитый код вообще нейтив кодом получится. Проблема только в кодогенерации.

Die-Hard ★★★★★
() автор топика
Ответ на: комментарий от Die-Hard

> Кодогенерить в машинные инструкции я не хочу: мне надо несколько архитектур, оно через два года устареет, появятся новые архитектуры, вставят защиту памяти, итп., и я не хочу потом всю жизнь это поддерживать.

Это настолько дешево и просто, что такие сомнения кажутся, извините, сомнительными. Что там, вообще, поддерживать?!? Всего лишь тупая арифметика.

> Можно будет попробовать какой-нибудь runtime assembler, типа GNU lightning, но боюсь, они генерят слишком долго и слишком generic код.

tcc поможет. Lightning не годится.

anonymous
()
Ответ на: комментарий от anonymous

> Это настолько дешево и просто, ...

Ну, мне не за это деньги платят. Конечно, все просто, если этим заниматься. Но нельзя заниматься всем сразу.

> tcc поможет. Lightning не годится.

Не понимаю. tcc -- СИшный компилятор. Как он мне может помочь сгенерировать из байткода нейтив? И почему не годится lightning?

Die-Hard ★★★★★
() автор топика
Ответ на: комментарий от Die-Hard

> Ну, мне не за это деньги платят.

А это, между прочим, fun. Да и нет там ничего сложного.

> Не понимаю. tcc -- СИшный компилятор.

Не просто сишный компилятор, а сишный компилятор, который умеет компилить в рантайме прямо в память. Никаких jit-ов не надо.

> И почему не годится lightning?

Потому, что для такого класса задач генерация инструкций lightning по сложности слабо отличается от генерации инструкций любой целевой платформы. Так что это только лишнее звено, причём довольно таки тормозное.

anonymous
()
Ответ на: комментарий от anonymous

> А это, между прочим, fun

Тут есть одна проблема: _разработка_ -- да, fun, но _поддержка_ -- нудная работа. Если я пойду по пути ручной кодогенерации мое творение через пару лет окажется никому не нужным, или мне придется постоянно его обновлять, читать про новые платформы итп. Но я, вообще-то, физик.

> Не просто сишный компилятор, а сишный компилятор, который умеет компилить в рантайме прямо в память. Никаких jit-ов не надо.

1. Может, не tcc, а lcc?

2. Но он СИ умеет компилить, текст перегонять в коды. А у меня гигабайты триад, массив структур вида "операция, адрес, адрес". И я не против его вручную перегнать в нейтив (вернее, с самого начала формировать эти триады в памяти в виде нейтив кодов), если бы не проблема с целевой платформой. Просто runtime assembler не устроит: мне ж нужно, чтобы оно везде работало. В этом смысле lightning (или подобное) -- вроде, именно то, что надо. Если оно, конецно, не шибко тормозное...

Die-Hard ★★★★★
() автор топика
Ответ на: комментарий от Die-Hard

> или мне придется постоянно его обновлять, читать про новые платформы итп.

Новая платформа - 10 строк кода. Какие трудности?

> 1. Может, не tcc, а lcc?

Да, конечно.

> 2. Но он СИ умеет компилить, текст перегонять в коды.

Я и предлагаю мелкие участки компилировать через Си, сами триады или их небольшие комбинации.

> Если оно, конецно, не шибко тормозное...

Я его года три тому назад щупал в последний раз, тогда оно было достаточно тормозным. Сейчас не в теме.

anonymous
()
Ответ на: комментарий от anonymous

> Новая платформа - 10 строк кода. Какие трудности?

Следить, читать, вникать, тестировать...

> Я и предлагаю мелкие участки компилировать через Си, сами триады или их небольшие комбинации.

И далее прямошитый код, теперь понял идею.

Это значит -- перегонять триады в текст, потом снова парсить. Тормозить будет. И как адреса а текст перегнать?

Die-Hard ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.