Добро пожаловать на Pro Pawn - Портал о PAWN-скриптинге.
Страница 1 из 3 1 2 3 ПоследняяПоследняя
Показано с 1 по 10 из 29
  1. #1
    Аватар для Salvacore
    Инжунер-погромист

    Статус
    Оффлайн
    Регистрация
    10.05.2013
    Адрес
    Аҧсуа бызшәа
    Сообщений
    2,271
    Репутация:
    418 ±

    Чистим массив игрока

    Функция
    PHP код:
    stock memset(aArray[], iValueiSize sizeof(aArray)) { 
        new 
    iAddress
        
    #emit LOAD.S.pri 12 
        #emit STOR.S.pri iAddress 
        
    iSize *= 4
        while (
    iSize 0) { 
            if (
    iSize >= 4096) { 
                
    #emit LOAD.S.alt iAddress 
                #emit LOAD.S.pri iValue 
                #emit FILL 4096 
                
    iSize -= 4096
                
    iAddress += 4096
            } else if (
    iSize >= 1024) { 
                
    #emit LOAD.S.alt iAddress 
                #emit LOAD.S.pri iValue 
                #emit FILL 1024 
                
    iSize -= 1024
                
    iAddress += 1024
            } else if (
    iSize >= 256) { 
                
    #emit LOAD.S.alt iAddress 
                #emit LOAD.S.pri iValue 
                #emit FILL 256 
                
    iSize -= 256
                
    iAddress += 256
            } else if (
    iSize >= 64) { 
                
    #emit LOAD.S.alt iAddress 
                #emit LOAD.S.pri iValue 
                #emit FILL 64 
                
    iSize -= 64
                
    iAddress += 64
            } else if (
    iSize >= 16) { 
                
    #emit LOAD.S.alt iAddress 
                #emit LOAD.S.pri iValue 
                #emit FILL 16 
                
    iSize -= 16
                
    iAddress += 16
            } else { 
                
    #emit LOAD.S.alt iAddress 
                #emit LOAD.S.pri iValue 
                #emit FILL 4 
                
    iSize -= 4
                
    iAddress += 4
            } 
        } 
        
    #pragma unused aArray 

    Использование
    PHP код:
    enum _:test 
        
    ID
        
    Float:POS
        
    NAME[MAX_PLAYER_NAME

    new 
    PLAYER[MAX_PLAYERS][test]; 
    public 
    OnPlayerDisconnect(playerid) { 
        
    memset(PLAYER[playerid],0_:test); 
        return 
    true

    Автор: Slice

  2. Пользователь сказал cпасибо:
    Glant (01.11.2016)
  3. #2
    Аватар для Profyan
    Пользователь

    Статус
    Оффлайн
    Регистрация
    23.12.2013
    Адрес
    Омск
    Сообщений
    196
    Репутация:
    22 ±
    Т.е за место того, чтобы 100500 строк писать(PI[playerid][Variable] =0,PI[playerid][Variable1] =0,PI[playerid][Variable2] =0...), можно использовать ее!?Насколько безопасна и эффективна эта функция?



    Любой дурак может написать код, понятный компьютеру. Хороший программист пишет код, понятный человеку
    Мартин Фаулер


    Skype
    profan99
    VK
    click




  4. #3
    Аватар для Daniel_Cortez
    "Это не хак, это фича"

    Статус
    Оффлайн
    Регистрация
    06.04.2013
    Адрес
    Novokuznetsk, Russia
    Сообщений
    2,192
    Репутация:
    2589 ±
    Цитата Сообщение от Profyan Посмотреть сообщение
    Т.е за место того, чтобы 100500 строк писать(PI[playerid][Variable] =0,PI[playerid][Variable1] =0,PI[playerid][Variable2] =0...), можно использовать ее!?Насколько безопасна и эффективна эта функция?
    Судя по коду, выход за предел буфера будет только если указать неправильный размер.

    Функция работает следующим образом: в наборе инструкций AMX есть опкод "fill", который заполняет блок данных, указанный в регистре alt значением из регистра pri. Этот опкод работает очень быстро, но в нём нельзя задать размер блока динамически, только в виде константы (динамически можно только указать через регистры адрес и значение). Поэтому в данной реализации memset массив разделяется на блоки по 4096, 1024, 256, 64, 16 и 4 байта, каждый из блоков заполняется своей инструкцией fill.

    По поводу оптимальности: запись в ячейки массива с помощью обычного цикла работает куда медленнее. Даже если оптимизировать такой цикл с помощью #emit и в цикле вместо счётчика использовать адрес текущей ячейки, такой цикл будет выигрывать только на небольших массивах (до 31 ячейки).
    Можете взять профайлер и проверить моё утверждение (регулируйте размер массива в PROFILER_ARRAY_SIZE):
    PHP код:
    /*Настройки.*/
    const PROFILER_ITERATIONS_MAJOR 1_000_000;
    const 
    PROFILER_ITERATIONS_MINOR 10;

    new const 
    code_snippets_names[2][] =
    {
        {
    "memset by Slice"},
        {
    "memset by Daniel_Cortez"}
    };


    const 
    PROFILER_ARRAY_SIZE 31;

    stock memset(aArray[], iValueiSize sizeof(aArray)) {
        new 
    iAddress;
        
    #emit LOAD.S.pri 12
        #emit STOR.S.pri iAddress
        
    iSize *= 4;
        while (
    iSize 0) {
            if (
    iSize >= 4096) {
                
    #emit LOAD.S.alt iAddress
                #emit LOAD.S.pri iValue
                #emit FILL 4096
                
    iSize -= 4096;
                
    iAddress += 4096;
            } else if (
    iSize >= 1024) {
                
    #emit LOAD.S.alt iAddress
                #emit LOAD.S.pri iValue
                #emit FILL 1024
                
    iSize -= 1024;
                
    iAddress += 1024;
            } else if (
    iSize >= 256) {
                
    #emit LOAD.S.alt iAddress
                #emit LOAD.S.pri iValue
                #emit FILL 256
                
    iSize -= 256;
                
    iAddress += 256;
            } else if (
    iSize >= 64) {
                
    #emit LOAD.S.alt iAddress
                #emit LOAD.S.pri iValue
                #emit FILL 64
                
    iSize -= 64;
                
    iAddress += 64;
            } else if (
    iSize >= 16) {
                
    #emit LOAD.S.alt iAddress
                #emit LOAD.S.pri iValue
                #emit FILL 16
                
    iSize -= 16;
                
    iAddress += 16;
            } else {
                
    #emit LOAD.S.alt iAddress
                #emit LOAD.S.pri iValue
                #emit FILL 4
                
    iSize -= 4;
                
    iAddress += 4;
            }
        }
        
    #pragma unused aArray
    }

    memset2(array[], valuesize sizeof(array))
    {
        
    #pragma unused array
        
    static addrend_addr;
        const 
    cell_size cellbits charbits;
        
    #emit    load.s.alt    array
        #emit    stor.alt    addr
        #emit    load.s.pri    size
        #emit    smul.c        cell_size
        #emit    add
        #emit    stor.pri    end_addr
        
    do
        {
            
    #emit    load.alt    addr
            #emit    load.s.pri    value
            #emit    stor.i
        
    }
        while((
    addr += cell_size) != end_addr);
    }


    #define Prerequisites();\
        
    new array[PROFILER_ARRAY_SIZE];

    #define CodeSnippet1();\
        
    memset(array, 0);

    #define CodeSnippet2();\
        
    memset2(array, 0);
    /*Конец настроек.*/ 
    Реализация от Slice проигрывает на массивах менее 32 элементов, но всё равно выигрывает на массивах по 24 (16 + 8), 16, 12 (8 + 4) и 9 ячеек, т.к. его алгоритм оптимизирован под блоки размером со степени двойки.
    Индивидуально в ЛС по скриптингу не помогаю. Задавайте все свои вопросы здесь (click).

  5. Пользователь сказал cпасибо:
    Profyan (26.12.2015)
  6. #4
    Аватар для Profyan
    Пользователь

    Статус
    Оффлайн
    Регистрация
    23.12.2013
    Адрес
    Омск
    Сообщений
    196
    Репутация:
    22 ±
    Цитата Сообщение от Daniel_Cortez Посмотреть сообщение
    Судя по коду, выход за предел буфера будет только если указать неправильный размер.

    Функция работает следующим образом: в наборе инструкций AMX есть опкод "fill", который заполняет блок данных, указанный в регистре alt значением из регистра pri. Этот опкод работает очень быстро, но в нём нельзя задать размер блока динамически, только в виде константы (динамически можно только указать через регистры адрес и значение). Поэтому в данной реализации memset массив разделяется на блоки по 4096, 1024, 256, 64, 16 и 4 байта, каждый из блоков заполняется своей инструкцией fill.

    По поводу оптимальности: запись в ячейки массива с помощью обычного цикла работает куда медленнее. Даже если оптимизировать такой цикл с помощью #emit и в цикле вместо счётчика использовать адрес текущей ячейки, такой цикл будет выигрывать только на небольших массивах (до 31 ячейки).
    Можете взять профайлер и проверить моё утверждение (регулируйте размер массива в PROFILER_ARRAY_SIZE):
    PHP код:
    /*Настройки.*/
    const PROFILER_ITERATIONS_MAJOR 1_000_000;
    const 
    PROFILER_ITERATIONS_MINOR 10;

    new const 
    code_snippets_names[2][] =
    {
        {
    "memset by Slice"},
        {
    "memset by Daniel_Cortez"}
    };


    const 
    PROFILER_ARRAY_SIZE 31;

    stock memset(aArray[], iValueiSize sizeof(aArray)) {
        new 
    iAddress;
        
    #emit LOAD.S.pri 12
        #emit STOR.S.pri iAddress
        
    iSize *= 4;
        while (
    iSize 0) {
            if (
    iSize >= 4096) {
                
    #emit LOAD.S.alt iAddress
                #emit LOAD.S.pri iValue
                #emit FILL 4096
                
    iSize -= 4096;
                
    iAddress += 4096;
            } else if (
    iSize >= 1024) {
                
    #emit LOAD.S.alt iAddress
                #emit LOAD.S.pri iValue
                #emit FILL 1024
                
    iSize -= 1024;
                
    iAddress += 1024;
            } else if (
    iSize >= 256) {
                
    #emit LOAD.S.alt iAddress
                #emit LOAD.S.pri iValue
                #emit FILL 256
                
    iSize -= 256;
                
    iAddress += 256;
            } else if (
    iSize >= 64) {
                
    #emit LOAD.S.alt iAddress
                #emit LOAD.S.pri iValue
                #emit FILL 64
                
    iSize -= 64;
                
    iAddress += 64;
            } else if (
    iSize >= 16) {
                
    #emit LOAD.S.alt iAddress
                #emit LOAD.S.pri iValue
                #emit FILL 16
                
    iSize -= 16;
                
    iAddress += 16;
            } else {
                
    #emit LOAD.S.alt iAddress
                #emit LOAD.S.pri iValue
                #emit FILL 4
                
    iSize -= 4;
                
    iAddress += 4;
            }
        }
        
    #pragma unused aArray
    }

    memset2(array[], valuesize sizeof(array))
    {
        
    #pragma unused array
        
    static addrend_addr;
        const 
    cell_size cellbits charbits;
        
    #emit    load.s.alt    array
        #emit    stor.alt    addr
        #emit    load.s.pri    size
        #emit    smul.c        cell_size
        #emit    add
        #emit    stor.pri    end_addr
        
    do
        {
            
    #emit    load.alt    addr
            #emit    load.s.pri    value
            #emit    stor.i
        
    }
        while((
    addr += cell_size) != end_addr);
    }


    #define Prerequisites();\
        
    new array[PROFILER_ARRAY_SIZE];

    #define CodeSnippet1();\
        
    memset(array, 0);

    #define CodeSnippet2();\
        
    memset2(array, 0);
    /*Конец настроек.*/ 
    Реализация от Slice проигрывает на массивах менее 32 элементов, но всё равно выигрывает на массивах по 24 (16 + 8), 16, 12 (8 + 4) и 9 ячеек, т.к. его алгоритм оптимизирован под блоки размером со степени двойки.
    Спасибо за разъяснение.Будет время - протестирую.



    Любой дурак может написать код, понятный компьютеру. Хороший программист пишет код, понятный человеку
    Мартин Фаулер


    Skype
    profan99
    VK
    click




  7. #5
    Аватар для Mopok
    Пользователь

    Статус
    Оффлайн
    Регистрация
    28.10.2015
    Сообщений
    37
    Репутация:
    3 ±
    Из выше разложенного непонятного для восприятия ламерским мозгом разъяснения по поводу данной функции, а также учитывая непонятое соответствие названия темы с тем же разъяснением, можно ли сделать вывод в двух словах, что данная функция ускоряет запись определённой переменной определённого массива и использует меньше памяти?
    Последний раз редактировалось Mopok; 26.12.2015 в 21:53.

  8. #6
    Аватар для Profyan
    Пользователь

    Статус
    Оффлайн
    Регистрация
    23.12.2013
    Адрес
    Омск
    Сообщений
    196
    Репутация:
    22 ±
    Цитата Сообщение от Mopok Посмотреть сообщение
    Из выше разложенного непонятного для восприятия ламерским мозгом разъяснения по поводу данной функции, а также учитывая непонятое соответствие названия темы с тем же разъяснением, можно ли сделать вывод в двух словах, что данная функция ускоряет запись определённой переменной определённого массива и использует меньше памяти?
    По поводу оптимальности: запись в ячейки массива с помощью обычного цикла работает куда медленнее. Даже если оптимизировать такой цикл с помощью #emit и в цикле вместо счётчика использовать адрес текущей ячейки, такой цикл будет выигрывать только на небольших массивах (до 31 ячейки).
    Внимательней читайте.



    Любой дурак может написать код, понятный компьютеру. Хороший программист пишет код, понятный человеку
    Мартин Фаулер


    Skype
    profan99
    VK
    click




  9. #7
    Аватар для Mopok
    Пользователь

    Статус
    Оффлайн
    Регистрация
    28.10.2015
    Сообщений
    37
    Репутация:
    3 ±
    О, спасибо, что бы я без умников делал, наверно никогда не читал бы внимательней. Нашёл ответ на англоязычном форуме, здесь полагаю если хочешь понять, нужно априори уже разбираться и понимать, также что именно она там чистит это инфа для прошаренных. Претензий не имею. Спс.

  10. #8
    Аватар для Mopok
    Пользователь

    Статус
    Оффлайн
    Регистрация
    28.10.2015
    Сообщений
    37
    Репутация:
    3 ±
    Эффективнее ли использовать функцию в присвоении не всему массиву определённого значения, а одной ячейке в отдельности?

  11. #9
    Аватар для Daniel_Cortez
    "Это не хак, это фича"

    Статус
    Оффлайн
    Регистрация
    06.04.2013
    Адрес
    Novokuznetsk, Russia
    Сообщений
    2,192
    Репутация:
    2589 ±
    Цитата Сообщение от Mopok Посмотреть сообщение
    Эффективнее ли использовать функцию в присвоении не всему массиву определённого значения, а одной ячейке в отдельности?
    Зачем использовать функцию для записи всего в одну ячейку, когда можно записать в неё значение напрямую?
    Если вы не понимаете разницы, то лучше не задумывайтесь о подобных оптимизациях, не то наделаете чего-нибудь, не разобравшись.
    Индивидуально в ЛС по скриптингу не помогаю. Задавайте все свои вопросы здесь (click).

  12. #10
    Аватар для TheMallard
    Пользователь

    Статус
    Оффлайн
    Регистрация
    08.12.2015
    Адрес
    San Fierro
    Сообщений
    217
    Репутация:
    39 ±
    Код:
    for(new pInfo:e; e < pInfo; ++e) PlayerInfo[playerid][e] = 0;

 

 
Страница 1 из 3 1 2 3 ПоследняяПоследняя

Информация о теме

Пользователи, просматривающие эту тему

Эту тему просматривают: 1 (пользователей: 0 , гостей: 1)

Ваши права

  • Вы не можете создавать новые темы
  • Вы не можете отвечать в темах
  • Вы не можете прикреплять вложения
  • Вы не можете редактировать свои сообщения
  •