Nemůžu svůj předchozí komentář změnit, tak doplňuji tímto: Místo použití “go fnc(...)” byste v C použil “dispatch_async(queue, ^{ fnc(...); })”, kde queue se vytvoří s DISPATCH_QUEUE_CONCURRENT (default je tuším SERIAL, takže by se nevytížila všechna jádra procesoru). Místo kanálu “done” byste musel použít dispatch_semaphore_t. To je asi vše podstatné.
Není zač, klidně se ozvěte, kdybyste k tomu ještě něco potřeboval. Jinak to s tím clangem není vlastně tak úplně pravda, v libdispatch mají funkce jako dispatch_async i varianty s příponou _f beroucí ukazatel na funkci a ukazatel na data, který se předá asynchronně volané funkci, takže i s gcc se dá libdispatch použít, jen to je trochu méně pohodlné.
Bylo by zajímavé ten původní benchmark přepsat do Fortranu a pustit na to intelácký překladač, který by moh uměl paralelizaci automaticky.
https://software.intel.com/en-us/articles/automatic-parallelization-with-intel-compilers/
V C++ se da krasne skalovat pomoci OpenMP (#pragma omp parallel for schedule(static)) v nejvnejsejsi smycce.
Co je problem, ze to moc nefunguje s printfem(dokonce se to brutalne zpomali). Oplati se dokonce nasypat vysledky do alokovaneho pole a to pak seriove projit a vyblit ven. Vzdycky je ale output brutalne pomalej. Na mem systemu v 8 vlaknech samotny vypocet 4096x4096x255 trva cca 0.140s - kazde bliti vysledku udela minimalne 3.5s(serializuju nasypane pole).
Nevim, jestli se to vubec da na tom benchmarkovat, kdyz io dela takovy obrovsky rozdil.
Pozn.: data v poli opravdu jsou, vypocet se neodoptimalizovava... kontroloval jsem to nekolika vypisy z pole.
No on tenhle benchmark je prakticky stejnej jako benchmark "mandelbrot" z klasicky "The Computer Language Benchmarks Game". Konkretne reseni v C s pouzitim OpenMP je napriklad tady: https://benchmarksgame-team.pages.debian.net/benchmarksgame/program/mandelbrot-gcc-8.html
Dalsi reseni pro Go, Fortran atd se daji najit na ty samy strance.
JJ a přesně proto jsou tam obě části, aby bylo vidět, jak se ovlivňují a že primitivní I/O v Go je v tomto ohledu limitující a výsledky úplně změní v neprospěch Go (i když opět říkám, že Go nedělá tak dobré optimalizace jako gcc a llvm). Můžeme si to samozřejmě přepsat naopak - načíst bitmapu s očekávaným výsledkem, potom provést výpočet a nakonec porovnat výsledek se vstupní bitmapou (to porovnání bude součástí benchmarku samozřejmě kvůli případným lazy výpočtům, načtení bude mimo).
Možná ještě doplním info, které jsem v článku nedopsal: ty výsledky jsou do posledního pixelu shodné, ovšem v C/C++ jde používat optimalizace typu --ffast-math apod., které dodají výsledky jiné, protože se přesně nedodrží IEEE 754. Proto tyto optimalizace v Makefile nejsou, naschvál samozřejmě.
Když už jsou tady ty benchmarky, jeden zajímavý byl nedávno publikován. Porovnává výsledky pod velkou I/O zátěží u tří populárních "cloudových" jazyků, node.js, Go a Elixir (Erlang). A Go si vede velmi dobře, především v celkové efektivitě.
Zdroj: https://stressgrid.com/blog/benchmarking_go_vs_node_vs_elixir/