<bgdev />free

| |  


All tags 2023 9may ai algorithm alpha amd american api argon2 arm asm asmbb assembler attachment awareness balgaria bay888 bcrypt bender beta bgdev-next bgdev-next.👍 big.data bitchnigga bitcoin bmw boi borg brexit bug bulgaria business c cad chat cloud computer-names console crossorigin deprivation desktop dna dotnet email eupl falling feature forum foundation fp fresh fun game github goats google gpl gpt gpt.3.5 gypsies happiness harvard hash improvement include investment it java javascript js kleta kleta.maqka.balg lambi language learning leftovers legend level levenshtein.dist libx license linkedlist linux ma mcafee mele microsoft minimag minimalism negro net nginx nigga not.a.bug oop paradigm parler patterns perception persuasion pipe play.station politics populi pornhub pow pro programming protonmail python reba rust sci-fi scripting seks seo server shell sleep smartbeauty soft-skills sqlite srabska sse starship sugerface syntax tablet tailwindcss telegram theme thug troll80lvl tutanota typescript uacme ui uk unix untermensch upload uptime usa utilities ux vb via viber virtual.reality vox vps vulnerable war wasm weapons-grade web windows word x86 xbox xss youtube zig ziglang Übermensch БОКЕБЪЛГАРИН БЪ БЪлгария Белезниците Били Били.Белезниците БялДонор Веган Виста Възраждане ГЛУПАК Гана Глиста ЕС Казарма Копейкин Мода.и.овча.мисъ НЕКАДЪРНИК НРБ ПО-ЗЛЕ.И.ОТ.РАБИ Подкасти Разни Румен СИК СКУМ СетенЧук Скум ТИР Туче Украйна Урсула Яначков авангард аз айфонджия алгоритми амбиции анархизъм антиваксъри армения аудио аутисти бази.данни бакъп без без.пръчове безпросвета бенчмарк биготи биомаса бира боклук борисов ботев брадва булшит бъг бъгове бял ваксина вандал век венерика викинги вицове вишу война вървежен гана ганорник гей гейщина германия герои гешев глупак говеда групировка гюбек данъкоплатец двойни.стандарти дедотия демокрация дизайн дисциплина добитък докери долар донори држава дришльо дрон ебане еврогейски.съюз езици експеримент електроника електроника.s2 емиграция ендпойнт енум ерген ергономия жалкар задача затоплизъм защита здраве златен злато игри идеали идиократ идиократи идиокрация идиот избори избори.рабин изкуство икономика имбецили имейл инвестиране инокулация инструмента интервю ипад искам.да.си.реда казах камшикодържач капитализъм карабах караница картечница кино клавиатура ковид19 колайдер колям.кур комари комплексар комунизъм консолидация конспирации космонавтика кофа кофит-19 краставица криптовалути курви кучелюбци лайно лаладжия лаптоп либерастия литература лоши.практики луд лъжеучени лъжец любов майни майтапи малоумници мафия мениджмънт месо местене метавселена метафизика механика мистика мисъл мода мода.овча.мисъл модерация морал мутра мутри наука национализъм не.it негър некадърник некадърници неон нидерландия овча овчи олигофрени организация офтопик парички партия педал пенджури пенсия пишока плюскане победа погромист поезия политика порно посредствен почивка празници прасе превод предалщина програмиране проект проста простотии против.правилата проф пръч пръч.дришльо пръчка психика психични.болести психология пустиняк путин путката путьо рабин рабин.е.шибан.пе работа радост разврат разни разработка расизъм резерват рейтинг реклама рекламен религия рест ризи ропче ропчета русия руски.език рутина самоковска сасипаха секира село селяндур сериали сериозно.програм сетен сеянин симулация скопяване скръм слушалки сортиране софия софтуер софтуни социализъм спектрометър спринтове сране стандарти стил стуйо стюи сушилня сцена съвет съм сън сървър сърничка таб ташаци телевизия тема територията терминология термояд технологии титли традиция тролинг тръмп туба туче тъпак тъпанари тъпня уиндоус украйна умнокрасивци фалит фантастика фашизъм фейк.акаунти физика филми форум форумни.проекти футбол хазарт хамали харабия хардуер хахаха хомофобия хостинг храна хумор цайко цайси целофан цензура цензурра циганин чалга чалгар чекии чернокраки честота чипове чнг чужбина чук шпация щайга юан яката яко ям 🔨 😂 🪓


Задача НЕ за интервю

  

0 1 2 3 4 ...8 9 10 11 12 ...18 19 20 21 22 ...26 27 28 29 30 ...32 33 34 35 36


  gat3way  Създадено на 28.09.2020, видяно: 1895 пъти. #12988
Евлампи
gat3way

Въпреки всичко, човек не трябва да изпада в такъв идеализъм и резултатите върху GPU-та са доста по-консистентни и независими от разни външни условия.

Така е ама както сам виждаш има разни неща дето са неочевидни и скалирането на решение не е гарантирано линейно и има разни скрити цени дето не е много ясно как се амортизират. Меренето и оптимизациите са тънка работа

Е, скалирането е друг проблем, но като цяло проблемът с profile-ването и оптимизациите ако и да звучи странно, е доста по-прост върху GPU-та, то там всичко е по-просто. Като цяло, GPU кода е далеч по-благ просто защото обикновено не може да става и дума за сравнение като комплексност с CPU кода. Съответно много по-лесно се осмисля какво и как да се промени. Това хубаво не е тривиално все пак наистина, щото си има неговите номера, наложени от хардуера, но всичко е (беше поне) доста добре документирано, и AMD и NVidia имаха мноооого чудни документи по въпроса за писането на читави кернели и утилизиране на хардуера доколкото може. Дори, колкото и да е тъпо, към един момент, дизасемблираните кернели за AMD ми се виждаха по-четливи и разбираеми от x86 асемблера, въпреки че това беше отпреди GCN, с оная малоумна VLIW архитектура, с клаузите, слотовете по клаузите и прочее тъпотии. С GCN (а и при nvidia) е още по-просто и четливо.



  johnfound  Създадено на 28.09.2020, видяно: 1885 пъти. #12989
|

Да, затова пуснах C кода. Няма как да пусна кода на Го, защото зависи от твърде много други файлове. Като преработя версията на tries за C може да я пусна и нея.

Мисля, че имаш грешка в тeзи два реда:

  start = ts.tv_sec * 1000.0 + ts.tv_nsec / 10000000.0; 
...
  end = ts.tv_sec * 1000.0 + ts.tv_nsec / 10000000.0; 

За да преобразуваш ns в ms трябва да делиш на 1Е6, а не на 1Е7.

Не е голям проблем - реално на моята машина грешката е около 500ms в твоя полза. ;-)



  ФейкПрофил  Създадено на 28.09.2020, видяно: 1884 пъти. #12990
johnfound
|

Това е кода на чисто C, който сравнява всеки със всеки стринг. На моят лаптоп това е резултата от първите 10 стринга:


0: 4 2011.848800 ms
1: 4 2011.129300 ms
2: 4 2012.483100 ms
3: 4 2012.424100 ms
4: 40 2911.208800 ms
5: 4 2013.644900 ms
6: 9 2011.395600 ms
7: 6 2019.304200 ms
8: 4 2011.881200 ms
9: 6 2021.873200 ms
10: 58 2915.040600 ms

О, мерси, ще имам някакви опорни стойности на какъв хардуер работиш и какво с какво сравняваме. :-)

При мене същият сорс дава:

0: 4 12943.155175 ms
1: 4 12042.569583 ms
2: 4 12948.384989 ms
3: 4 12050.330475 ms
4: 41 12948.288226 ms
5: 4 12044.346433 ms
6: 9 12948.630645 ms
7: 6 12044.806212 ms
8: 4 12045.221166 ms
9: 6 12949.675423 ms
10: 58 12048.351350 ms

Тоест, твоят компютър е приблизително 6 пъти по-бърз от моят.

Впрочем, мисля, че намерих причината за големите забавяния - последните версии на Intel имат ужасни латентности на някои инструкции, при това неочевидни... :-(

Левенщайна ти е бавен :) аз исках да ускоря моя, но това което намерих като "оптимизиран" алгоритъм се оказа 2пъти по-бавен от библиотечката която ползвах :Д

Единствената оптимизация, която успях да направя е да ползвм u8 вместо char, което смъкна 500мс на стринг и стана ~3450мс



  |  Създадено на 28.09.2020, видяно: 1882 пъти. #12991
johnfound
|

Да, затова пуснах C кода. Няма как да пусна кода на Го, защото зависи от твърде много други файлове. Като преработя версията на tries за C може да я пусна и нея.

Мисля, че имаш грешка в тeзи два реда:

  start = ts.tv_sec * 1000.0 + ts.tv_nsec / 10000000.0; 
...
  end = ts.tv_sec * 1000.0 + ts.tv_nsec / 10000000.0; 

За да преобразуваш ns в ms трябва да делиш на 1Е6, а не на 1Е7.

Не е голям проблем - реално на моята машина грешката е около 500ms в твоя полза. ;-)

Ugh, натиснал съм една нула повече. Мерси. :)



  Delegate  Последно редактирано на 28.09.2020 от Delegate, видяно: 1879 пъти. #12992

ФейкПрофил, и аз мисля, че му е бавен Левенщ*ейнът*. Тоя C# вариант, при мен е по-бърз от неговия.


 public static int LevenshteinDistance(string value1, string value2)
        {
            if (value1.Length == 0)
            {
                return 0;
            }

            int[] costs = new int[value1.Length];

            // Add indexing for insertion to first row
            for (int i = 0; i < costs.Length; )
            {
                costs[i] = ++i;
            }

            int minSize = value1.Length < value2.Length ? value1.Length : value2.Length;


            for (int i = 0; i < minSize; i++)
            {
                // cost of the first index
                int cost = i;
                int addationCost = i;

                // cache value for inner loop to avoid index lookup and bonds checking, profiled this is quicker
                char value2Char = value2[i];

                for (int j = 0; j < value1.Length; j++)
                {
                    int insertionCost = cost;

                    cost = addationCost;

                    // assigning this here reduces the array reads we do, improvment of the old version
                    addationCost = costs[j];

                    if (value2Char != value1[j])
                    {
                        if (insertionCost < cost)
                        {
                            cost = insertionCost;
                        }

                        if (addationCost < cost)
                        {
                            cost = addationCost;
                        }

                        ++cost;
                    }

                    costs[j] = cost;

                }


            }

            return costs[costs.Length - 1];
        }



  |  Последно редактирано на 28.09.2020 от |, видяно: 1871 пъти. #12993
gat3way

Ами спокойно може да съм го окензал някъде, не съм го тествал особено много.

Хмм, това __local в OpenCL като __shared__ в CUDA ли е? Ако да, в levenshtein използваш един и същи буфер за всички тредове. Ако не е, res и off в reduce ще са грешни.



  gat3way  Създадено на 28.09.2020, видяно: 1855 пъти. #12995

Оооо даммм, прав си. Требва да е двумерен масив и да се индексира спрямо get_local_id(0). Обаче 64 му идва прекалено много иииии...

ptxas error   : Entry function 'levenshtein' uses too much shared data (0xc804 bytes, 0xc000 max)

Затва, трябва да се ограничи workgroup size-а на 32 вместо 64. Това обаче естествено води до прилично влошаване на производителността....иииии...

execution time = 55.904923 seconds


  |  Създадено на 28.09.2020, видяно: 1848 пъти. #12996
gat3way

Оооо даммм, прав си. Требва да е двумерен масив и да се индексира спрямо get_local_id(0). Обаче 64 му идва прекалено много иииии...

ptxas error   : Entry function 'levenshtein' uses too much shared data (0xc804 bytes, 0xc000 max)

Затва, трябва да се ограничи workgroup size-а на 32 вместо 64. Това обаче естествено води до прилично влошаване на производителността....иииии...

execution time = 55.904923 seconds

Има още един бъг, за B трябва да сетваш и използваш temp2, a не temp.

Иначе аз пробвах да направя column да се алокира в “стека” като махнах local, но като че ли стана още по-бавно от твоето.



  gat3way  Създадено на 28.09.2020, видяно: 1844 пъти. #12997

Не, не го прави това, двумерен масив в local, индексиран спрямо workitem-а е по-добре. Иначе компилатора си решава къде ще отиде това в "стека" и това спокойно може да свърши в глобалната памет. В opencl-а е много важно да се казва в кой memory space кое ходи, иначе компилатора прави каквото си реши и това често изобщо не е умно. Той може и много умни неща да направи, ако например масивът е малък и има наклонности, може да отиде в регистри, но (поне при AMD навремето), тея неща често ходеха в това дето му викаха "scratch register space" или нещо от сорта което си е глобална памет пар екселанс.

Нещо от сорта:

__kernel void levenshtein(__global const uchar *A, __global const uchar *B, __global uint *C, uint index) 
{
    uint s1len, s2len, x, y, lastdiag, olddiag;
    uint temp, temp2;
    uint i = get_local_id(0);
    __local uint column[32][MAX_STRING];

    int j = get_global_id(0);
    temp = j * (MAX_STRING+sizeof(uint));
    s1len = (A[temp+3] << 24) | (A[temp+2] << 16) | (A[temp+1] << 8) | A[temp];
    temp = index * (MAX_STRING+sizeof(uint));
    s2len = (B[temp+3] << 24) | (B[temp+2] << 16) | (B[temp+1] << 8) | B[temp];


    for (y = 1; y <= s1len; y++)
        column[i][y] = y;
    for (x = 1; x <= s2len; x++) 
    {
        column[i][0] = x;
        for (y = 1, lastdiag = x-1; y <= s1len; y++) 
        {
            olddiag = column[i][y];
            column[i][y] = MIN3(column[i][y] + 1, column[i][y-1] + 1, lastdiag + (A[temp + sizeof(int) + y-1] == B[temp + sizeof(int) + 
x - 1] ? 0 : 1));
            lastdiag = olddiag;
        }
    }

    C[i] = column[i][s1len];
}

И в хост кода size_t local_item_size става 32 (но за reduce, трябва да се въведе друг local_item_size дето пак си е 64).



  |  Създадено на 28.09.2020, видяно: 1838 пъти. #13000
gat3way

Не, не го прави това, двумерен масив в local, индексиран спрямо workitem-а е по-добре. Иначе компилатора си решава къде ще отиде това в "стека" и това спокойно може да свърши в глобалната памет. В opencl-а е много важно да се казва в кой memory space кое ходи, иначе компилатора прави каквото си реши и това често изобщо не е умно. Той може и много умни неща да направи, ако например масивът е малък и има наклонности, може да отиде в регистри, но (поне при AMD навремето), тея неща често ходеха в това дето му викаха "scratch register space" или нещо от сорта което си е глобална памет пар екселанс.

Нещо от сорта:

__kernel void levenshtein(__global const uchar *A, __global const uchar *B, __global uint *C, uint index) 
{
    uint s1len, s2len, x, y, lastdiag, olddiag;
    uint temp, temp2;
    uint i = get_local_id(0);
    __local uint column[32][MAX_STRING];

    int j = get_global_id(0);
    temp = j * (MAX_STRING+sizeof(uint));
    s1len = (A[temp+3] << 24) | (A[temp+2] << 16) | (A[temp+1] << 8) | A[temp];
    temp = index * (MAX_STRING+sizeof(uint));
    s2len = (B[temp+3] << 24) | (B[temp+2] << 16) | (B[temp+1] << 8) | B[temp];


    for (y = 1; y <= s1len; y++)
        column[i][y] = y;
    for (x = 1; x <= s2len; x++) 
    {
        column[i][0] = x;
        for (y = 1, lastdiag = x-1; y <= s1len; y++) 
        {
            olddiag = column[i][y];
            column[i][y] = MIN3(column[i][y] + 1, column[i][y-1] + 1, lastdiag + (A[temp + sizeof(int) + y-1] == B[temp + sizeof(int) + 
x - 1] ? 0 : 1));
            lastdiag = olddiag;
        }
    }

    C[i] = column[i][s1len];
}

И в хост кода size_t local_item_size става 32 (но за reduce, трябва да се въведе друг local_item_size дето пак си е 64).

Да, аз пробвах да го направя и uchar, но е по-бавно от свалянето на броя тредове. На теслата е 24 секунди за 1000 стринга.



  gat3way  Създадено на 28.09.2020, видяно: 1836 пъти. #13001

Ами аз както казах, доскоро не бях писал кернел от поне две години :)

Но иначе, навремето (и за амд и за нвидия), гранулярността за достъп до всякаква памет беше 32 бита. Като достъпваш uchar, пак четеш 32 бита, но имплицитно се шибват маските и това е по-бавно (отделно и там конфликтите при достъпа на памет когато се пише, които са сходни като идея с false sharing-а при CPU-то). Но да де, когато имаш ограничения на паметта, това може и да излезе по-добрият вариант. То затва ми липсва amdappprofiler-а, беше много хубаво нещо. Със сигурност има нещо и за nvidia сега, тогава нямаше толкова яко, но нвидията много дръпна последните години и сигурно имат вече по-добро. То всъщност май и тогава имаха, но беше само за куда-та май. Абе всъщност не знам.



  |  Създадено на 28.09.2020, видяно: 1814 пъти. #13003
gat3way

Ами аз както казах, доскоро не бях писал кернел от поне две години :)

Но иначе, навремето (и за амд и за нвидия), гранулярността за достъп до всякаква памет беше 32 бита. Като достъпваш uchar, пак четеш 32 бита, но имплицитно се шибват маските и това е по-бавно (отделно и там конфликтите при достъпа на памет когато се пише, които са сходни като идея с false sharing-а при CPU-то). Но да де, когато имаш ограничения на паметта, това може и да излезе по-добрият вариант. То затва ми липсва amdappprofiler-а, беше много хубаво нещо. Със сигурност има нещо и за nvidia сега, тогава нямаше толкова яко, но нвидията много дръпна последните години и сигурно имат вече по-добро. То всъщност май и тогава имаха, но беше само за куда-та май. Абе всъщност не знам.

На мен твоя код ми харесва повече от моя, но за съжаление не скейлва добре. 200К стринга ги сравнява за 4688 секунди, докато моя го прави за 1335.

От друга страна, за 1000 стринга твоя му трябват 23.9 секунди, докато на моя 118.3.

Предполагам, че твоите кърнъли са too fine grained и овърхеда за стартирането се акумулира.



  gat3way  Създадено на 28.09.2020, видяно: 1812 пъти. #13004

Чакай сега че съм на друга вълна, спуквам се от смях, тоя яко е огаврил алтернативките-десни тука.



  Golden Gega  Създадено на 29.09.2020, видяно: 1797 пъти. #13010
gat3way

Чакай сега че съм на друга вълна, спуквам се от смях, тоя яко е огаврил алтернативките-десни тука.

Хахаха, тоя пич плюс цивренето на Рамбо дават добър старт на деня, а и спря да вали rofl



  Delegate  Последно редактирано на 29.09.2020 от Delegate, видяно: 1784 пъти. #13012
ФейкПрофил
Delegate

Малко я барнах заявката - чувствително подобрение. Не ползвам сторнати процедури.

Successfully run. Total query runtime: 5 min 41 secs.
100 rows affected.

Абе нещо пак не е така. Задачата е за всеки от 100-те хиляди стринга да намериш най-близкия от другата колекция. С други думи, решението ти трябва да произведе 100_000 реда на изхода.

ПП: задачата много прилича на spellchecker обаче там алгоритмите се издъниха здраво :Д Както казва мастър Линус - когато теорията и практиката се сблъскат, практиката винаги печели.

Еми, на Джони програмката например вади 100 резултата, не 100 000. От друга страна, оригиналното условие на | е :

Колекция А е от 1 милион стринга, колекция Б е от 10 милиона стринга.

За всеки стринг от колекция Б трябва да се намери стринга от колекция А, който е най-близък до него.

Джон, ти защо вадиш само 100 резултата и при това редицата ти от резултати 4,4,4,4,40,4,9 ти е одобренa от | :-)



  ФейкПрофил  Създадено на 29.09.2020, видяно: 1778 пъти. #13017

Тази редица е одобрена. Май оригиналното условие просто е наобратно - за всеки от 100те трябва да се намери най-близкия от 100–000



  Delegate  Създадено на 29.09.2020, видяно: 1760 пъти. #13029

Някой, ако иска да тества C# версия (exe)

Attached files:
FileSizeUploadedDownloadsMD5 hash
leven.zip3458656 bytes29.09.2020143d591d3fb2c55246916365eb7a955b943


  Courvoisier  Създадено на 29.09.2020, видяно: 1756 пъти. #13031
Delegate

Някой, ако иска да тества C# версия (exe)

Дай сорс де, exe да изпълнявам от интернета малко....



  synergie  Създадено на 29.09.2020, видяно: 1755 пъти. #13032
Courvoisier
Delegate

Някой, ако иска да тества C# версия (exe)

Дай сорс де, exe да изпълнявам от интернета малко....

Пусни го у некой контейнер.



  Delegate  Последно редактирано на 29.09.2020 от Delegate, видяно: 1751 пъти. #13033

А на Джони изпълнихте екзето, а ? rofl

using System;
using System.Collections.Generic;
using System.Text;
using System.IO;

namespace Leven
{
    class Program
    {
        public static int Distance(string value1, string value2)
        {
            if (value1.Length == 0)
            {
                return 0;
            }
            int[] costs = new int[value1.Length];
            // Add indexing for insertion to first row
            for (int i = 0; i < costs.Length; )
            {
                costs[i] = ++i;
            }

            int minSize = value1.Length < value2.Length ? value1.Length : value2.Length;
            for (int i = 0; i < minSize; i++)
            {
                // cost of the first index
                int cost = i;
                int addationCost = i;

                // cache value for inner loop to avoid index lookup and bonds checking, profiled this is quicker
                char value2Char = value2[i];

                for (int j = 0; j < value1.Length; j++)
                {
                    int insertionCost = cost;
                    cost = addationCost;
                    // assigning this here reduces the array reads we do, improvment of the old version
                    addationCost = costs[j];
                    if (value2Char != value1[j])
                    {
                        if (insertionCost < cost)
                        {
                            cost = insertionCost;
                        }
                        if (addationCost < cost)
                        {
                            cost = addationCost;
                        }
                        ++cost;
                    }
                    costs[j] = cost;
                }
            }
            return costs[costs.Length - 1];
        }

        static void Main(string[] args)
        {

            var ListA = File.ReadAllLines("Dataset.txt");
            var ListB = File.ReadAllLines("t2.txt");
            List<string> lineListB = new List<string>(ListB);
            List<string> lineListA = new List<string>(ListA);

            //var watch = System.Diagnostics.Stopwatch.StartNew();

            for (int i = 0; i < lineListB.Count; i++)
            {
                var watch = System.Diagnostics.Stopwatch.StartNew();
                int min_dist = Int32.MaxValue;

                for (int j = 0; j < lineListA.Count; j++)
                {
                    int dist = Distance(lineListB[i], lineListA[j]);
                    if (dist < min_dist)
                    {
                        min_dist = dist;
                    }
                }

                watch.Stop();
                Console.WriteLine(i + " elapsed (ms)/dist:" + watch.ElapsedMilliseconds + "/" + min_dist);

            }


        }

    }
}




0 1 2 3 4 ...8 9 10 11 12 ...18 19 20 21 22 ...26 27 28 29 30 ...32 33 34 35 36


Задача НЕ за интервю

  



AsmBB v3.0 (check-in: 7544654b24928b93); SQLite v3.47.0 (check-in: 03a9703e27c44437);
©2016..2024 John Found; Licensed under EUPL; Powered by Assembly language Created with Fresh IDE