среда, 3. фебруар 2010.

Проблем

Управо сам суочен са интересантним проблемом који још увек не знам да решим. Ради се о седећем:

Имам блок меморије, унутар њега елементе са заглављем и слободним простором. Уколико је задато поравнање поинтера, треба да нађем поинтер у једном од слободних простора који је поравнан на дату вредност. Другим речима, уколико имам поинтер p, и величину елемента (заглавље + слободни простор), да ли је могуће доказати да постоји такав цели број N за који ће следећа једначина да важи:

p + N * dist = M * alignment

где су
p - поинтер на први слободни простор блока
N - произвољни цели број
dist - величина елемента (заглавље + слободни простор)
M - произвољни цели број
alignment - поравнање, мора бити 2 на целобројни експонент.


----

После мало размишљања, математика би могла да буде ово:

Формулу поделим са alignment:

p / alignment + N * dist / alignment = M

Резултат дељења би могао бити:

P + Mp / alignment + N * dist / alignment = M

С обзиром да доказујем само да ли постоје такви целобројни N и M, није битно која је њихова вредност, па онда целобројну вредност P стапам са M i dobijam neki novi celobrojni broj R.

Mp / alignment + N * dist / alignment = R

Да би горња једначина била задовољена, рационални број треба да нестане, а то може само ако:

N * dist = alignment - Mp

односно

N = (alignment - Mp) / dist

Дакле уколико је остатак овог дељења 0, такви бројеви постоје:

if (mod((alignment - mod(p / alignment))/dist) == 0) -> Da
else -> NE


----
После пуно размишљања, и дискусије са Страхињом, мој закључак је да таква општа формула не постоји. На крају сам променио алгоритам за испитивање подобности датог блока и сада је овакав.

Ако су сви следећи услови испуњени, блок је подобан:

1. Све корисничке алокације унутар блока су поравнате на 2^k адресе (другим речима, првa корисничка адреса унутар блока је 2^k)
2. Тражено поравање је такође 2^k
3. Величина алокационог елемнта (кориснички простор + контролна структура) мора бити такође 2^k
4. Тражено поравање мора бити мање или једнако величини алокационог елемента.

Тако се алокација врши само ако су задовољени горе наведени услови, а све остало се одбацује и алокација се врши од општег "list allocator".

11 коментара:

  1. Према Архимедовом својству, за сваки мањи број a<b постоји природан број n такав да ако n пута сабереш мањи број, збир пређе или буде једнак b.

    И сад само кажеш да је b=2^k...

    ОдговориИзбриши
  2. Моја математика није довољно добра да бих размео како то могу да искористим.

    Оно што видим у садашњој имплементацији је да се користи претпоставка да су dist и alignment производ унапред дефинисаног целог броја (у нашем случају 8) и произвољне целобројне константе. Провера се састоји у једноставном:

    if ((dividend = (alignment / dist)) <= p->nalloc
    && dividend * p->esize == alignment) { /* an even multiple */

    (где је p->nalloc укупан број елемената у блоку)

    Mеђутим, мислим да је ово погрешно у општем случају јер за, на пример, alignment = dist = 128 погрешно закључује да такав елемент постоји чак и ако први елемент није поравнан на 128 бајтова.

    ОдговориИзбриши
  3. Па, питао си како би се доказала једнакост. Зато сам навео теорему преко које би се доказала.

    А сама алокација би морала да пролази кроз листу слободних региона и да за сваки посебно проверава да ли је довољно велики да се у њега смести нов садржај.

    ОдговориИзбриши
  4. У суштини то је оно што тренутно и ради, најпре провери да ли величина одговара.

    Међутим, после тога у петљи покушава да "поравна" поинтер у слободим елементима. Тај део ми се и даље чини као груба сила, али не умем да нађем ништа боље. Мислио сам да може математички да се докаже да ли такав поинтер теоретски може да постоји у датом ниѕу елемената, и то у првих nalloc елемената.

    ОдговориИзбриши
  5. Аха, мислим да ми је јасно шта желиш да постигнеш. Међутим, опет ти треба пролаз кроз листу, зато што не можеш унапред, без провере, да знаш да ли је неки, назовимо га тако, „подрегион“, слободан или не.

    Да би избегао опсежнију претрагу, можеш, алтернативно, да одвојено одржаваш сортирану листу слободних подрегиона, али то компликује алокацију и све операције са меморијом.

    Бар ја не видим боље решење. Можда оно постоји код Кнута у „The Art of Computer Programming“? Е, ако га тамо нема, онда сигурно боље решење и не постоји.

    ОдговориИзбриши
  6. Тренутно спремам „Вероватноћу и статистику“, па могу да Ти кажем да вероватноћа увек постоји, само је питање колика је. :-)

    0 <= P(A) <= 1

    Иначе, ово би био занимљив задатак из Вероватноће, само је проблем што не знаш ништа од података у вези са постојећим заузећем меморије.

    ОдговориИзбриши
  7. Ево још неких формула.

    Претпоставимо да је меморија „исцепкана“ на регионе. Сваки регион почиње на адреси која је степен двојке, 2^k (k је унапред задато).

    Ако је блок меморије алоциран у оквиру региона, регион у коме се он налази се може добити овако:
    reg(p)=((p>>k(<<k)
    где је >> десни шифт, а << леви (дељење и множење степеном двојке, редом).

    Позиција блока у оквиру региона се добија формулом:
    pos(p)=p-reg(p)

    ОдговориИзбриши
  8. С тим што је:
    reg(p)=((p>>k)<<k)

    *уздах* :-(

    Волео бих да Блогер подржава уређивање коментара, а не само брисање.

    ОдговориИзбриши
  9. Ово је мало скретање са теме:
    Алокациона шема код нас (кју ен екс) се састоји од два приступа: један општи алокатор који алоцира произвољну величину меморије и један "small block" алокатор који уноси одрђене претпоставке, као на пример да су интерно доступни блокови фиксне величине.

    Свака алокација почиње са мапирањем стране меморије у адресни простор апликације. То се ради у целобројним бројевима страница (које су обично 4 килобајта). Затим се на почетак такве стране поставља структура која повезује све стране које припадају датој величини алокације, затим структура која описује блок одонсно садржи поинтер на први слободни комад меморије. Сваки комад меморије почиње структуром која, када је комад слободан, садржи поинтер на следећи слободан комад, а када је заузет садржи офсет до струкутре блока.

    Алокација и деалокација оваквих "комада" је врло ефикасна: при алокацији се просто врати поинтер из блока, а на његово место се упише вредност из комада на који показује, па се онда препише поинтер комада да постане офсет.



    Све је то у реду. Оно што сам у теми описивао није општи алгоритам алокације, који је урађен добро, односно ја не могу да смислим ништа боље, него конкретно сучај када се са memalign захтева меморија поравнана на неку 2^k адресу при чему је захтевана величина довољно мала да алокатор одлучи да то треба да иде из "брзог" алокатора малих блокова. Ту постоји проблем.

    ОдговориИзбриши
  10. > поравнана на неку 2^k адресу при чему
    > је захтевана величина довољно мала да
    > алокатор одлучи да то треба да иде из
    > "брзог" алокатора малих блокова.

    То већ представља нешто друго. :-)

    ОдговориИзбриши