[C++] Varie

hamming_burst
Salve,
chiedo alcuni pareri.


    [*:4mfr7zeg] inizializzazione matrici. Il memset() del C è utilizzato in C++, c'è forse di meglio come efficienza? Un doppio ciclo for è più stabile? parlo di matrici inteso come nel C, array di array non std::vector, ...

    [/*:m:4mfr7zeg]
    [*:4mfr7zeg] hashing. Sto provando a fare qualche ottimizzazione sul confronto di righe di una matrice. Su C++ reference ho scoperto che c'è già implementata una funzione hash() http://www.cplusplus.com/reference/std/ ... late/hash/
    #include <iostream>
    #include <cstring>
    #include <locale>
    
    int main(){
    
    	unsigned short lon = 100;
    	unsigned char data[lon];
    
    	memset((void*)data,1,lon*sizeof(unsigned char));
    
    	std::locale loc;  
    
    	const std::collate<char>& coll = std::use_facet<std::collate<char> >(loc);
    
    	long myhash = coll.hash(data,data+lon);
            // long myhash = coll.hash((char*)data,(char*)data+lon);
    	std::cout << myhash << std::endl;
    
    }
    

    Utilizzando unsigned char ricevo l'errore di bad_casting. Perciò facendo un casting a char sembra funzionare. Non so però quanto possa essere fedele una funzione hash con tale casting, anche se non vedo troppi problemi in merito.
    Qualcuno conosce la funzione e sa dirmi se è affidabile.[/*:m:4mfr7zeg][/list:u:4mfr7zeg]

    Ringrazio

Risposte
claudio862
"hamming_burst":
Salve,
chiedo alcuni pareri.


    [*:j6iu93g6] inizializzazione matrici. Il memset() del C è utilizzato in C++, c'è forse di meglio come efficienza? Un doppio ciclo for è più stabile? parlo di matrici inteso come nel C, array di array non std::vector, ...

std::memset() per azzerare un array funziona come in C, purché il tipo dell'array sia abbastanza semplice (vedi documentazione, i tipi primitivi vanno bene).
Non penso che un doppio ciclo sia più efficiente, ma probabilmente non cambia molto.


"hamming_burst":
[/*:m:j6iu93g6][*:j6iu93g6] hashing. Sto provando a fare qualche ottimizzazione sul confronto di righe di una matrice. Su C++ reference ho scoperto che c'è già implementata una funzione hash() http://www.cplusplus.com/reference/std/ ... late/hash/
[…]
Utilizzando unsigned char ricevo l'errore di bad_casting. Perciò facendo un casting a char sembra funzionare. Non so però quanto possa essere fedele una funzione hash con tale casting, anche se non vedo troppi problemi in merito.
Qualcuno conosce la funzione e sa dirmi se è affidabile.[/*:m:j6iu93g6][/list:u:j6iu93g6]

Sei nella sezione "locale" della libreria standard. Queste funzioni dovrebbero essere usate solo su stringhe. Onestamente non so se unsigned char rispetti i requisiti per essere usato come carattere di stringa, però nella libreria standard non ci sono specializzazioni a riguardo (ci sono solo per char, wchar_t, char16_t e char32_t).
In ogni caso non mi fiderei molto ad usare un hash pensato per stringhe di testo su dati generici, anche perché l'algoritmo di hash è dipendente dall'implementazione.

char, signed char e unsigned char sono tipi diversi tra loro, quindi non puoi convertire automaticamente un array di uno in un array di un altro. Usa reinterpret_cast(data) (e dimenticarti dei cast C). Comunque hanno la stessa dimensione quindi il cast è valido.
Qua altre informazioni.


Ah, "lon" deve essere costante, in C++ non esistono array a lunghezza variabile:
unsigned short lon = 100;
unsigned char data[lon];

apatriarca
Riguardo a memset. E' spesso implementato in assembler usando tutte le capacità di questo linguaggio. Per cui è potenzialmente più veloce rispetto ad un ciclo (e spesso lo è non solo in potenza).

hamming_burst
Vi ringrazio.

Altra cosa:
    [*:1i7t9qw7]seek line. Dato un file di testo, dovrei spostare la posizione corrente del puntatore di lettura ad una linea prestabilita. Provato es. con:
    std::ifstream file.
    file.open("pippo.txt", std::ios::in|std::ios::binary);
    
    file.seekg(10,std::ios::beg);
    

    Non funziona (tralasciate i controlli). Quale è la giusta sintassi?[/*:m:1i7t9qw7][/list:u:1i7t9qw7]

    Ringrazio

vict85
Perché leggi il file in binary? E poi non ti stai spostando di linee ma di byte (penso). Un modo semplice consiste nel contare i \n nel file.

claudio862
seekg() si sposta di N byte o caratteri, non linee. Il modo più semplice è di leggere N linee.

std::ifstream file.
file.open("pippo.txt");

for (int i = 0; i < 10; ++i) {
    std::string s;
    std::getline(file, s);
    if (file.fail()) {
        // Errore, il file non conteneva 10 linee.
    }
}


In effetti non aprirei il file in binario se contiene del testo. Non c'è nemmeno bisogno di specificare std::ios:in, perché è il valore di default per std::ifstream.

hamming_burst
"vict85":
Perché leggi il file in binary?

bella domanda... :D

E poi non ti stai spostando di linee ma di byte (penso). Un modo semplice consiste nel contare i \n nel file.

"claudio86":
seekg() si sposta di N byte o caratteri, non linee. Il modo più semplice è di leggere N linee.

std::ifstream file.
file.open("pippo.txt");

for (int i = 0; i < 10; ++i) {
    std::string s;
    std::getline(file, s);
    if (file.fail()) {
        // Errore, il file non conteneva 10 linee.
    }
}


In effetti non aprirei il file in binario se contiene del testo. Non c'è nemmeno bisogno di specificare std::ios:in, perché è il valore di default per std::ifstream.

ok perciò $n$ letture di linee a vuoto, speravo qualcosa di più efficiente (per questo pensavo che seekg lavorasse su linee).
$n$ è abb grande, così a freddo dovrebbe arriavere anche a 25000 nel caso pessimo. Se non c'è altro modo devo cambiare tipo di strutturazione in input.

vict85
25000 linee? Ma leggi un codice? Comunque puoi puntare sulla costruzione di un qualche albero che ti permetta di ricercare una linea in modo più efficiente (anche se la costruzione di questa struttura richiede di leggere tutto il file).

apatriarca
Qualche piccola domanda:
1. Perché stai utilizzando un file binario se vuoi accedervi in modo casuale?
2. Quanto è grosso il file?
3. Quanti di questi accessi devi eseguire durante una singola esecuzione del programma?
4. Desideri effettuare anche delle modifiche al file? Le potenziali modifiche sono inframmezzate alle letture oppure le seguono?
5. Le righe hanno una qualche struttura particolare?
6. Hai la possibilità di cambiare il formato del file in ingresso?

hamming_burst
vediamo...
"apatriarca":
Qualche piccola domanda:
1. Perché stai utilizzando un file binario se vuoi accedervi in modo casuale?

quello è stato solo un copia/incolla da un'altra struttura che scrive in altro modo..

2. Quanto è grosso il file?

caso pessimo 2MByte
3. Quanti di questi accessi devi eseguire durante una singola esecuzione del programma?

togliendo le funzioni di posizionamento, scandisco sequenzialmente ad intervalli di circa 300 linee per quattro/cinque volte.
4. Desideri effettuare anche delle modifiche al file? Le potenziali modifiche sono inframmezzate alle letture oppure le seguono?

la concorrenza è ridotta a solo letture. L'esistenza di tale file è il risultato di operazioni (complesse) pregresse, diciamo che serve come memoria di massa.
5. Le righe hanno una qualche struttura particolare?

stringa unica con spazzatura finale (utilizzata per altro) perciò deve esserci parsing comunque.
6. Hai la possibilità di cambiare il formato del file in ingresso?

No. Massimo rinominare con mv prima dell'esecuzione.

Non devo accedere in modo casuale, ma sequenziale, perchè gli intervalli li riordino e sono indipendenti, per questo una funzione di posiziomanteo efficiente penso basti.

"vict85":
Comunque puoi puntare sulla costruzione di un qualche albero che ti permetta di ricercare una linea in modo più efficiente (anche se la costruzione di questa struttura richiede di leggere tutto il file).

il salvataggio di tale file è per filtrare una serie di dati (complessi), ricrearne una più piccola dal file, complicherebbe troppo le cose.

per il momento vi ringrazio dell'interessamento.

apatriarca
Dalle tue risposte mi sembra chiaro che il metodo migliore sia quello di caricare l'intero file in memoria, memorizzando la posizione di ogni riga in un array di supporto all'inizio dell'esecuzione (o caricare il file in un array/lista di righe). 2MB di dimensione massima sono decisamente pochi per preoccuparsi delle perfomance in realtà.. Ma è abbastanza piccolo da essere contenuto per intero in molte cache L2..

Rispondi
Per rispondere a questa discussione devi prima effettuare il login.