Byla vydána nová verze 2.47.0 distribuovaného systému správy verzí Git. Přispělo 83 vývojářů, z toho 28 nových. Přehled novinek v příspěvku na blogu GitHubu a v poznámkách k vydání.
Bylo vydáno OpenBSD 7.6. Opět bez písničky.
Programovací jazyk Python byl vydán v nové major verzi 3.13.0. Podrobný přehled novinek v changelogu.
Lze získat roota pouze se zapalovačem? Ano, lze.
Konference LinuxDays 2024 proběhne již tento víkend 12. a 13. října v Praze. Na programu je spousta zajímavých přednášek a workshopů, zástup zajímavých osobností a stánky řady projektů: Fedora, openSUSE, vpsFree.cz, Mozilla, brmlab, OpenAlt a mnoho dalších. Vstup zdarma.
Představeny byly oficiální Raspberry Pi microSD karty třídy A2 a silikonový kryt na Raspberry Pi 5.
OpenRazer byl vydán ve verzi 3.9.0. Jedná se o svobodný software, ovladač a démon, umožňující nastavovat klávesnice, notebooky, myši, podložky pod myš, keypady, sluchátka a další zařízení od společnosti Razer na GNU/Linuxu.
Byla vydána verze 3.6 multiplatformního integrovaného vývojového prostředí (IDE) pro rychlý vývoj aplikaci (RAD) ve Free Pascalu Lazarus (Wikipedie). Přehled novinek v poznámkách k vydání. Využíván je Free Pascal Compiler (FPC) 3.2.2.
Na čem aktuálně pracují vývojáři GNOME a KDE? Pravidelný přehled novinek v Týden v GNOME a Týden v KDE.
Byla vydána nová verze 8.8 multiplatformní digitální pracovní stanice pro práci s audiem (DAW) Ardour. Přehled oprav, vylepšení a novinek v oficiálním oznámení.
typedef struct {
float** fDataA; //2D array of ...
...
}Data2;
typedef struct{
float a[3];
int b[4];
int c;
string string;
Data2 data2;
...
} Data;
int allocateData(Data **data,...){
*data = (Data*) malloc( pocetDat * sizeof(Data));
for(int y = 0;y < pocetDat; y++){
(*data)[y].data2.fDataA = (float**) malloc((*data)[y].data2.pocetDat2*sizeof(float*));
for(int i = 0;i < pocetDat2;i++){
(*data)[y].data2.fDataA[i] = (float*) malloc(pocetDat3*sizeof(float));
}
}
... //dalsi dynamicke alokace, overeni, jestli se to opravdu alokovalo...
}
int freeData(mainData **data){
for(int y = 0;y < pocetDat; y++){
for(int i = 0;i < pocetDat2; i++){
free((*data)[y].data2.fDataA[i]);
}
}
free(*data);
}
readData(Data **data,...){
...
allocateData(data,...);
...
//nactu hodnoty do data
...
}
main(){
Data *data;
...
readData(&data,...);
...
printf("integer %i",data[2586].b[4]);
freeData(&data);
}
*data = (Data*) malloc(spocitanaVelikost);
?
Malloc je použit protože to původně bylo v C a až do teď jsem nějak nepřemýšlel v čem se vlastně tak liší od New.
Jenže Data a Data2 jsou struktury, ne třídy, takže jejich konstruktory použít nemůžu i když by se tím asi dost věcí zjednodušilo.
Vlasně možná by nemuseli být - budu k tomu muset udělat binding do Pythonu, který znám jen z rychlíku, ale předpokládal jsem, že bude vhodnější nechat data ve strukturách, než ve třídách, což asi nemusí být pravda. Struktura Data se předává mezi knihovnou a programem a nějak jsem předpokládal, že bude vhodnější předávat data ve struktuře a ne ve třídě, co je taky asi jedno....
fDataA[i*pocetDat2+y] místo fDataA[i][y]
,ale podle mě při takovém množství dat ta malá úspora paměti na úkor přehlednosti nemá cenu. Rychlost alokace je v porovnání s rychlostí načítání dat zanedbatelná. Jediný problém tuším v tom, že data nebudou v paměti za sebou, což nedokážu posoudit, jaký může mít vliv.
int allocateData(Data **data,...){
*data = new Data[pocetDat];
for(int y = 0;y < pocetDat; y++){
(*data)[y].data2.fDataA = new float*[pocetDat2];
for(int i = 0; i < pocetDat2; ++i){
(*data)[y].data2.fDataA[i] = new float[pocetDat3];
}
}
...
}
int freeData(Data **data,...){
for(int y = 0;y < pocetDat; y++){
for(int i = 0;i < pocetDat2; i++){
delete [] (*data)[y].data2.fDataA[i];
}
delete [] (*data)[y].data2.fDataA;
}
delete [] *data;
}
struct Data2 { std::vector<std::vector<float>> fDataA; // ... }; struct Data { float a[3]; float b[4]; int c; string string; Data2 data2; // ... }; int allocateData(std::vector<Data>& data, ...) { data.resize(pocetDat); for (size_t y = 0; y < pocetDat; ++y) { Data& dy = data[y]; dy.data2.fDataA.resize(pocetDat2); for (size_t i = 0; i < pocetDat2; ++i) { dy.data2.fDataA[i].resize(pocetDat3); } } // blabla } int freeData(std::vector<Data>& data) { // aneb vyser se na malloc a free data.clear(); }
int freeData(std::vector<Data>& data) { // aneb vyser se na malloc a free data.clear(); }optimističtější varianta by musela vypadat asi takto nějak:
int freeData(std::vector<Data>& data) { data.clear(); // aneb vyser se na malloc a free std::vector<Data> tmp; data.swap(data); }Jinak vector určitě jo, nicméně pokud to má mít i malé paměťové nároky, tak bohužel jen jeden a počítat si to růčo a přistupovat k prvkům přes
at()
, ale zamyslel bych se nad tím, jestli mi opravdu vadí použít vector vector-ů při drobném navýšení nároků. Kdyby se jednalo o miliony a více záznamů, tak to má význam, ale tísíce znamená 10tis, což je asi 280KB navíc).
int freeData(std::vector<Data>& data) { // aneb vyser se na malloc a free data.clear(); std::vector<Data>& tmp; data.swap(tmp); }
typedef struct{ float ttt[3][4][25]; }myrec; std::vector<myrec> data;
g++ kuk.cpp -o kuk
), ono vector je super, ale zrovna ve správě paměti se lehce naseká spousta chyb (platí pro celou stl).typedef struct {
u64 neco;
u8 neco2;
u8 neco3;
float pole1[4];
float pole2[4];
... /dalsi data - celkem 846B dat ulozenych vetsinou ve ve 4 prvkovych float polich s pevnou delkou
//nasleduje pet poli o ktere mi ted jde predevsim - na testovacich datech jsou tri
//z nich o velikosti 4*25 a dve prazdne. Maximalne muze v soucasne dobe mit kazde
//velikost 4*50. Velikost poli neznam v dobe kompilace, ale v dobe volani allocateData
//uz jo a nikdy se potom nemeni.
float *dulezitePole1; /**< 2D array of ... */
float *dulezitePole2; /**< 2D array of ... */
float *dulezitePole3; /**< 2D array of ... */
float *dulezitePole4; /**< 2D array of ... */
float *dulezitePole5; /**< 2D array of ... */
} Data;
allocateData(Data **data,...){
//pocetDat = pocet struktur Data je na testovacich datech 26000,
//v realu muze byt vyrazne min, ale i o dost vic.
*data = new Data[pocetDat];
for(int y = 0;y<pocetDat;y++){
(*data)[y].dulezitePole1 = new float[pocetDat21 * pocetDat3];
(*data)[y].dulezitePole2 = new float[pocetDat22 * pocetDat3];
(*data)[y].dulezitePole3 = new float[pocetDat23 * pocetDat3];
(*data)[y].dulezitePole4 = new float[pocetDat24 * pocetDat3];
(*data)[y].dulezitePole5 = new float[pocetDat25 * pocetDat3];
}
}
Když jsem místo float *dulezitePole1 zkoušel std::vector<float> dulezitePole1
a ve funkci allocateData použil dulezitePole1.resize(pocetDat21 * pocetDat3);
byla spotrebovana pamet jen o 0.5 MB vetsi nez pri pouziti float* a new.
Jenže použití std::vector
mi nepřineslo žádný viditelný užitek - stejně jsem si musel iterovat a pamatovat velikosti sám, protože dulezitePole1.size()
je mi k ničemu. Navíc zde dochází k tomu, že většina polí je float[4]
a 5 polí je std::vector
, což je matoucí - tu knihovnu nebudu používat jen já.
Když jsem použil std::vector
na všehny 4 prvkové pole floatů ve struktuře Data (je jich 50), tak paměťová náročnost vzrostla o 11,5MB.
int freeData(Data **data){
for(int y = 0;y < pocetDat; y++){
delete [] (*data)[y].dulezitePole1;
delete [] (*data)[y].dulezitePole2;
delete [] (*data)[y].dulezitePole3;
delete [] (*data)[y].dulezitePole4;
delete [] (*data)[y].dulezitePole5;
}
delete [] *data;
return 0;
}
Když místo resize použijete reserve, tak se sice paměť naalokuje, ale size bude ukazovat reálný počet prvků a přidávat pak budete pomocí push_back.
Na ta pole float[4] skutečně nemá cenu std::vector používat. Nevím co s těmi poli děláte, možná by zpřehlednění pomohl typedef či lépe nějaká obalující třída (pokud to jsou třeba quatermiony, tak se do obalující třídy dají přidat metody pro různé operace nad nimi, přetížit operátory a podobně).
Padesát čtyrprvkových polí ve struktuře mi trochu zavání špatným návrhem, opravdu to potřebujete takto udělat? Nestačilo by jedno padesátiprvkové pole tříd se čtyřmi floaty uvnitř?
Z mého pohledu má std::vector hlavní výhody v tom, že si nemusím udržovat počet prvků, v dealokaci a v čistotě kódu. Při vývoji velkých aplikací se mi to osvědčilo. Pokud tyto tři aspekty hodnotíte jinak, asi pro Vás nemá std::vector význam.
std::vector
a v Qt s oblibou požívám QVector a podobné kontejnery, jen pro jejich požití v tomhle konkrétním případě nevidím moc důvod, ale je možné, že mi pořád něco uniká...
Jenže std::vector je příliš paměťově náročný, když mam 26000 struktur Data, který sice obsahujou dynamicky alokovaný pole, ale ve všechn 26000 případech odpovídající pole mají stejný rozměr (což sem asi měl zmínit dřív) - takže tady 26000*5 ukládám ve std::vector kromě vlstních dat to samý - velikost + další režii, což mi ve výsledku zvýší paměťovou náročnost a skoro mi to nepomůže.
// vytvorenie pola objektov , !!pouziva def.konstruktor pre Data Data *data = new Data[pocetDat]; // dealokovanie objektov Data delete[] data; // alokovanie pola smernikov (pointer) na typ float (*data)[y].data2.fDataA = new float*[(*data)[y].data2.pocetDat2]; // alokovanie pola float-ov (*data)[y].data2.fDataA[i] = new float[pocetDat3]; // dealokovanie for(int y=;...;y++) for(int i;...;i++) delete (*data)[y].data2.fDataA[i] ; delete (*data)[y].data2.fDataA;
Tiskni Sdílej: