Zobrazit příspěvky

Tato sekce Vám umožňuje zobrazit všechny příspěvky tohoto uživatele. Prosím uvědomte si, že můžete vidět příspěvky pouze z oblastí Vám přístupných.


Příspěvky - MarekKnapek

Stran: [1]
1
Vývoj / Re:Zkrácení haše pro identifikaci
« kdy: 28. 02. 2024, 08:43:51 »
Pokud si ty hashe generujete sám, mohou se hodit algoritmy a kterých si můžete vybrat délku hashe. Pro spoustu use-case je to dobré řešení.

Doporučuji nějakou XOF funkci, třeba SHAKE (varianta SHA3).

3
Server / Re:Levné hostování velkého množství dat
« kdy: 14. 02. 2024, 04:20:13 »
Tady mají sice malý HDD ale unmetered traffic za 96$. Možná by to šlo spojit s úložištěm, které není dostupné všem z internetu, ale poze jednomu účtu (typu ulozto). https://www.fdcservers.net/configurator?fixedFilter=20&fixedFilterType=bandwidth_option

4
Server / Re:Levné hostování velkého množství dat
« kdy: 14. 02. 2024, 03:47:43 »
> Jinak take premyslim, zda do Hetzeru jit.

Mám tam malý server 16GB/8core/30€. Tuším že traffic je do 20TB zdarma. Linka zhruba 1.5Gbps. Za poslední rok 1 výpadek na zhruba 10 hodin. Žádné info ani omluva, když jsem se zeptal co se stalo, řekli mi, že na node kde běží můj server musela být provedena urgent maintenance.

5
Server / Re:Levné hostování velkého množství dat
« kdy: 01. 02. 2024, 01:10:17 »

6
Server / Re:Komprimovat či nekomprimovat data pro HTTP
« kdy: 14. 01. 2023, 21:05:37 »
samozrejme predkomprimovat subory je uplna blbost

To samozřejmě není. Došlo tu k nedorozumění, každý mluvíme o trochu něčem jiném. Já mluvím o statickém obsahu jako jsou například za prvé css a js součásti html, nebo za druhé csv, log, txt data ke stažení. Je lepší je 1x-3x zkomprimovat dopředu (pokaždé jinou metodou) a poté je x-krát poslat klientům na každý jejich požadavek (podle toho jakou umí kompresi). Přesně za tímto účelem Google v roce 2013 představil zopfli/brotli, program, který komprimuje do starého dobrého zlibu, který umí všechny současné i minulé prohlížeče, ALE produkuje mnohem menší soubory za cenu mnohem, mnohem, mnohem větší spotřeby CPU a RAM. To nám ale nevadí, protože komprimujeme pouze 1x a pak milionkrát posíláme již zkomprimovaný soubor a tím šetříme traffic a https šifrování.

Ty mluvíš o za prvé datech typu png, jpeg a mpeg. Ty už jsou uvnitř zkomprimované a je tedy nesmysl je dále komprimovat http kompresí. Co je ale možné, je mít na serveru x variant stejného obrázku/fotky nebo videa v různých formátech jako je např. jpeg, jpeg-xl, heic, webp nebo mpeg, h264, h265, vp9, av1 a nabídnout klientovi všechny varianty a on si vybere tu nejlepší, kterou umí.

Za druhé mluvíš o výstupech z API, tam je to na zvážení, protože jde o dynamická data. Záleží na trade-off mezi časem potřebným k vygenerování dat + jejich kompresi vs ušetřený bandwidth. Na velmi pomalé lince se vyplatí komprimovat. To už tu rozebrali jiní diskutující.

7
Server / Re:Komprimovat či nekomprimovat data pro HTTP
« kdy: 13. 01. 2023, 17:28:54 »
Tady to vypadá jako nedostatek CPU, protože komprese probíhá on-line (v okamžiku vyřizování requestu). Hádám správně? Pokud ano, doporučuji komprimovat offline. To znamená, že dopředu vyberu statické resources, které chci komprimovat (typicky JavaScripty, txt logy, CSV dokumenty, apod), tyto 1x zkomprimuji pomocí zlib/brotli/gzip. Následně při vyřizování requestu se podívám jakou kompresi klient umí a podle toho vyberu (už zkomprimovaný) soubor na disku a pošlu ho.

8
Vývoj / Re:HMAC, SHA1 (C++/AVX2 VS2022)
« kdy: 03. 01. 2023, 03:33:43 »
Ahoj Kevile, matematika ti moc nejde, co? Říkáš, že zvládneš spočítat 62^8 netriviálních operací za 40 ms? To máme 62^8/40 netriviálních operací za ms, neboli 62^8/40/1000 netriviálních operací za μs, neboli 62^8/40/1000/1000 netriviálních operací za ns. Furt je to zhruba 5.5 miliónu netriviálních operací každou nanosekundu. Při rychlosti 5GHz, to je stále milión operací za takt. To asi ne, co?

9
Vývoj / Re:HMAC, SHA1 (C++/AVX2 VS2022)
« kdy: 10. 12. 2022, 00:12:10 »
Tak jsem se na to podíval a určitě tam máš chybu ve výpočtu SHA-1, ve druhém a dalším bloku, kód [1] nahraď kódem [2].

[1]
Kód: [Vybrat]
void SHA1(__m256i* indata) {
    uint32_t pole[80];
    __m256i data;

    uint32_t h0 = 0x67452301, a = h0;
    uint32_t h1 = 0xEFCDAB89, b = h1;
    uint32_t h2 = 0x98BADCFE, c = h2;
    uint32_t h3 = 0x10325476, d = h3;
    uint32_t h4 = 0xC3D2E1F0, e = h4;

    for (int k = 0; k < 2; k++) {

        data = _mm256_load_si256(indata + k * 2);
        _mm256_store_si256((__m256i*)pole, data);
        data = _mm256_load_si256(indata + k * 2 + 1);
        _mm256_store_si256((__m256i*)pole + 1, data );

        uint32_t temp;

        for (int i = 0; i < 80; i++) {

[2]
Kód: [Vybrat]
void SHA1(__m256i* indata) {
    uint32_t pole[80];
    __m256i data;

    uint32_t h0 = 0x67452301;
    uint32_t h1 = 0xEFCDAB89;
    uint32_t h2 = 0x98BADCFE;
    uint32_t h3 = 0x10325476;
    uint32_t h4 = 0xC3D2E1F0;

    for (int k = 0; k < 2; k++) {

        data = _mm256_load_si256(indata + k * 2);
        _mm256_store_si256((__m256i*)pole, data);
        data = _mm256_load_si256(indata + k * 2 + 1);
        _mm256_store_si256((__m256i*)pole + 1, data );

        uint32_t temp;
        a = h0;
        b = h1;
        c = h2;
        d = h3;
        e = h4;
        for (int i = 0; i < 80; i++) {

10
Vývoj / Re:HMAC, SHA1 (C++/AVX2 VS2022)
« kdy: 08. 12. 2022, 22:12:35 »
Ahoj, nedávno jsem implementoval (mimo jiné) jak SHA-1 tak HMAC v čistém C (C89/C90). Mám to na GitHibu a běží to i ve Visual Studiu. Je to otestované a funguje to zaručeně správně (použil jsem fuzzing a jako oracle Windows crypto API). Takže do mé implementace můžeš hodit svůj input a prokrokovat si to v debuggeru. Nepoužívám ovšem ani AVX ani SSE ani AES-NI. Je to k dispozici na https://github.com/MarekKnapek/mk_crypto/blob/refactor/fuzz/mk_mac_hmac_fuzz.c

11
S obnovou nepomůžu, ale poradím pro příště:

Abych mohl obnovit soubor, který jsem omylem smazal, používám funkci Windows Shadow Volume. V Linuxu by byl ekvivalent BTRFS nebo ZFS copy on write snapshot. Přidal jsem si naplánovanou úlohu, která se spouští jednou denně. Obnova pak probíhá z okna vlastností složky, je tam karta předchozí verze. Nemusím instalovat žádný nový program, stačí jednou nastavit a už na to nemusím myslet, funguje to automagicky samo od sebe.

12
Citace
zejména pokud je CRT linkována dynamicky (což je asi jediný legální způsob)

Není. Volba překladače /MT (případně /MTd) zajistí statické linkování CRT. To je důležité například když chcete distribuovat svou aplikaci jako jediné .exe bez dalších závislostí, které by se musely doinstalovávat (redist).

13
Napřed si probereme, jak se dají na Windows spouštět nová vlákna.

_beginthread a _beginthreadex nejsou funkce z Windows, ale z UCRT (Universal C Run-Time library). Na Linuxu by se dalo říci, že to je LibC. UCRT je nyní součástí Windows, ale dříve to tak nebylo (tuším že WinXP), musela se dodatečně doinstalovat (takzvaný redist). Doporučuji používat, pokud chceš nová vlákna vytvářet z programovacího jazyka C.

CreateThread je funkce z Windows, již od počátku věků. Doporučuji používat, pokud chceš nová vlákna vytvářet z assembleru, nebo z jiného programovacího jazyka, který nemá run-time, nebo máš ty, jako programátor, absolutní kontrolu nad tím run-time.

std::thread je třída ze standardní knihovny C++. Doporučuji používat, pokud chceš nová vlákna vytvářet z programovacího jazyka C++.

Ty používáš C++, proč tedy nepoužívat funkce _beginthread, _beginthreadex a CreateThread? Je to kvůli tomu, že tebou zvolený programovací jazyk má tzv. run-time. Nemůžeš si jen tak vytvořit nové vlákno a v něm začít vykonávat kód v tvém programovacím jazyku aniž bys mu o tom, že jsi vytvořil nové vlákno, řekl. Není nikdo, kdo by inicializoval prostředí, které ti tvůj programovací jazyk dává per-thread. V Cčku to je například proměnná errno.

Dále si probereme, jak se (obecně) používají vlákna.

Když spustíš svůj program, operační systém ti vytvoří hlavní vlákno a spustí tzv. entry-point funkci. Ta v tvém případě inicializuje C a C++ run-time, zavolá konstruktory globálních objektů, zaregistruje spuštění destruktorů globálních objektů při vypínání programu a udělá spoustu dalších věcí, mimo jiné zavolá tvoji main funkci (nebo wmain funkci nebo WinMain funkci nebo wWinMain funkci). Dále už je to na tobě, ty můžeš vytvořit další vlákna. Pravidlo slušnosti je takové, že je někdo, kdo "vlastní" to nově spuštěné vlákno a je zodpovědný za to, že počká, až skončí. Podobně jako když alokuješ paměť pomocí new nebo malloc, nebo když otevřeš soubor pomocí fopen nebo CreateFile. Vždy máš nějaký odkaz/ukazatel/handle na ten resource co jsi alokoval (pointer, file handle, FILE* pointer, thread handle, apod.). Tento resource musí někdo uklidit, v C++ se typicky používá RAII idiom (vygůgli si to) a úklid se děje v destruktoru. To znamená, že se zavolá delete/free/CloseHandle/fclose apod. Vlákna se "uklízejí" tak, že se mu "nějak" řekne, že se má ukončit a počká se na to, až se probere, zjistí, že se má ukončit a samo se ukončí. Jsou dva způsoby programování vláken (podle mě). "Jednorázová činnost" a "smyčka".

Tvůj případ bude asi "jednorázová činnost", to jest, v hlavním vlákně si připravíš nějaký task pro tvoje nové vlákno. Data, která má zpracovat a místo, kam má odevzdat výsledek. Pak spustíš nové vlákno a jako parametr mu předáš tento task. Vlákno běží, zpracovává task a když je hotov, tak odevzdá výsledek do připraveného místa, "nějak" ohlásí, že je hotovo a ukončí se.

Smyčka je nekonečná smyčka, kdy máš nějakou datovou strukturu (frontu) tasků, které má vlákno vykonat. Spustíš vlákno, předáš mu jako parametr odkaz na tu frontu a vlákno dělá následující: Je ve frontě nějaký task? Pokud ano, tak ho vykonej, ulož výsledek, "nějak" notifikuj, že je task hotový a jdi zpět na krok 1. Pokud ne, tak "nějak" zjisti, jestli se má ukončit a ukonči se. Pokud se nemá ukončit, tak čekej na nový task a jdi spát. Hlavní vlákno (nebo jakékoli jiné) pak může do fronty přidat nový task a probudit spící vlákno.

Všimni si, že jsem několikrát použil slovo "nějak". Tím jsem myslel mezivláknovou synchronizaci, to je téma na celý samostatný článek, to sem psát nebudu, prostuduj si věci jako jsou mutex, atomic variable, critical section, promise + future, condition variable, CreateEvent, WaitForSingleObject a další.

Píšeš, že očekáváš, že se práce ve vláknu bude dít na pozadí a na popředí bude tvoje aplikace reagovat na uživatelské vstupy. Ale přitom jsi žádný takový kód nenapsal. Aby se to dělo, musel bys napsat něco ve smyslu: 1) Připrav task. 2) Spusť nové vlákno a předej mu task. 3) Je task již hotový? Pokud ne, tak zpracuj uživatelovy vstupy (třeba animuj rotující kolečko o 5°) a vrať se na bod 3. Pokud ano, tak seber výsledek a něco s ním udělej. Nastuduj si jak se ve Windows píše tzv. smyčka zpráv (používají se k tomu funkce GetMessage a DispatchMessage).

Na závěr konečně nějaký ten kód (pozor nemám tady VisualStudio IDE, mám pouze staré command-line VisualStudio Build Tools 2013). Zkopíruj tento program a ulož ho do souboru test.cpp, spusť si z nabídky Start Visual Studio developer command prompt (nebo tak nějak se to jmenuje), na command line napiš dva příkazy, jeden pro zkompilování, druhý pros spuštění nového programu.

Marek

Kód: [Vybrat]
#include <chrono>
#include <future>
#include <iostream>
#include <mutex>
#include <thread>


std::mutex g_console_mutex;


void factorial(int zadani, std::promise<int>* vysledek_promise)
{
{
std::lock_guard<std::mutex> const lck{g_console_mutex};
std::cout << "Vlakno spusteno.\n";
}
int n = zadani;
int ret = 1;
for(int i = 0; i != n; ++i)
{
ret = ret * (i + 1);
std::this_thread::sleep_for(std::chrono::seconds(1));
{
std::lock_guard<std::mutex> const lck{g_console_mutex};
std::cout << "Vlakno pocita.\n";
}
}
vysledek_promise->set_value(ret);
}


int main()
{
{
std::lock_guard<std::mutex> const lck{g_console_mutex};
std::cout << "Program spusten.\n";
}
int zadani = 5;
std::promise<int> vysledek_promise;
std::future<int> vysledek_future = vysledek_promise.get_future();
int vysledek;
std::thread vlakno{&factorial, zadani, &vysledek_promise};
for(;;)
{
std::future_status status = vysledek_future.wait_for(std::chrono::seconds(0));
if(status != std::future_status::ready)
{
{
std::lock_guard<std::mutex> const lck{g_console_mutex};
std::cout << "Program ceka, ale dela praci na popredi.\n";
}
// Tady budes obsluhovat vstupy utivatele a GUI.
std::this_thread::sleep_for(std::chrono::milliseconds(333));
continue;
}
vysledek = vysledek_future.get();
{
std::lock_guard<std::mutex> const lck{g_console_mutex};
std::cout << "Hotovo, vysledek je: " << vysledek << ".\n";
}
break;
}
// Nezapomenout pockat na ukonceni vlakna, protoze sice jiz mame vysledek,
// vlakno jiz "vypadlo" z funkce factorial, ALE jeste stale bezi.
// Vykonava se uklizeci funkce C a C++ run-time, na vlakno pockame pomoci join.
vlakno.join();
}


Kód: [Vybrat]
cl.exe /EHcs test.cpp

Kód: [Vybrat]
test.exe

Kód: [Vybrat]
Program spusten.
Program ceka, ale dela praci na popredi.
Vlakno spusteno.
Program ceka, ale dela praci na popredi.
Program ceka, ale dela praci na popredi.
Vlakno pocita.
Program ceka, ale dela praci na popredi.
Program ceka, ale dela praci na popredi.
Program ceka, ale dela praci na popredi.
Vlakno pocita.
Program ceka, ale dela praci na popredi.
Program ceka, ale dela praci na popredi.
Program ceka, ale dela praci na popredi.
Vlakno pocita.
Program ceka, ale dela praci na popredi.
Program ceka, ale dela praci na popredi.
Program ceka, ale dela praci na popredi.
Vlakno pocita.
Program ceka, ale dela praci na popredi.
Program ceka, ale dela praci na popredi.
Program ceka, ale dela praci na popredi.
Vlakno pocita.
Hotovo, vysledek je: 120.


14
Proč to chceš omezovat? Co tím chceš získat?

Myslím si, že těch ušetřených 2× PCIe nepůjde využít pro jiné zařízení.

15
Jak už tu někteří psali:

IrfanView [1] umí hromadnou konverzi souborů včetně snížení počtu barev. Použít plug-in PNGOut. Nebo stand-alone verzi PNGOout. [2]

PNGCrush [3]

brotli / zopfli [4][5]

Pak mě ještě napadá: Kdo bude ty výsledné soubory konzumovat? Bude to běžný Franta uživatel? Nebo to bude software, který máš pod kontrolou ty (například web browser)? V v druhém případě bych alespoň zvážil variantu komprimovat do jiného formátu než je PNG. Například moderní bezeztrátové formáty vycházející z video komprese pro i-frame typu HEIF [6], WebP [7], BPG [8] a další.

Marek

[1] https://www.irfanview.com/
[2] http://advsys.net/ken/utils.htm
[3] https://pmt.sourceforge.io/pngcrush/
[4] https://github.com/google/brotli
[5] https://github.com/google/zopfli
[6] https://en.wikipedia.org/wiki/High_Efficiency_Image_File_Format
[7] https://en.wikipedia.org/wiki/WebP
[8] https://bellard.org/bpg/


Stran: [1]