Torna indietro   Hardware Upgrade Forum > Software > Programmazione

Recensione Samsung Galaxy Z Fold7: un grande salto generazionale
Recensione Samsung Galaxy Z Fold7: un grande salto generazionale
Abbiamo provato per molti giorni il nuovo Z Fold7 di Samsung, un prodotto davvero interessante e costruito nei minimi dettagli. Rispetto al predecessore, cambiano parecchie cose, facendo un salto generazionale importante. Sarà lui il pieghevole di riferimento? Ecco la nostra recensione completa.
The Edge of Fate è Destiny 2.5. E questo è un problema
The Edge of Fate è Destiny 2.5. E questo è un problema
Bungie riesce a costruire una delle campagne più coinvolgenti della serie e introduce cambiamenti profondi al sistema di gioco, tra nuove stat e tier dell’equipaggiamento. Ma con risorse limitate e scelte discutibili, il vero salto evolutivo resta solo un’occasione mancata
Ryzen Threadripper 9980X e 9970X alla prova: AMD Zen 5 al massimo livello
Ryzen Threadripper 9980X e 9970X alla prova: AMD Zen 5 al massimo livello
AMD ha aggiornato l'offerta di CPU HEDT con i Ryzen Threadripper 9000 basati su architettura Zen 5. In questo articolo vediamo come si comportano i modelli con 64 e 32 core 9980X e 9970X. Venduti allo stesso prezzo dei predecessori e compatibili con il medesimo socket, le nuove proposte si candidano a essere ottimi compagni per chi è in cerca di potenza dei calcolo e tante linee PCI Express per workstation grafiche e destinate all'AI.
Tutti gli articoli Tutte le news

Vai al Forum
Rispondi
 
Strumenti
Old 30-05-2006, 10:53   #1
riemann_01
Member
 
Iscritto dal: May 2006
Messaggi: 38
[C++] funzione memcpy

[Post modificato]

Salve a tutti!
Ho re-implementato la funzione memcpy per cercare di capirne al meglio il significato e l'utilizzo.
Codice:
// memcpy.cc

#include <iostream>
using namespace std;

void* memcpy(void* s1, const void* s2, unsigned lenght)
{
	const char* from = (const char*)s2;
	char* to = (char*)s1;
	
	while (lenght != 0) {
		*to++ = *from++;
		--lenght;
	}
	return s1;
}

int main()
{
	char* src = "prova";
	char* dest = new char[strlen(src)+1];
	
	cout << "source: " << src << endl;
	char* result = (char*)memcpy(dest,src,strlen(src)+1); 
	cout << "destination: " << result << endl;
}
Cio' che non riesco ad interpretare correttamente e' il tipo di ritorno. A che serve?
Il puntatore to e' automatic, quindi lo spazio di memoria riservato alla stringa in stile C viene liberato dopo l'ultima istruzione return.
In che modo si potrebbe utilizzare un indirizzo iniziale di una sequenza di caratteri alfanumerici gia' deallocata?

Ultima modifica di riemann_01 : 31-05-2006 alle 13:27.
riemann_01 è offline   Rispondi citando il messaggio o parte di esso
Old 30-05-2006, 10:58   #2
andbin
Senior Member
 
L'Avatar di andbin
 
Iscritto dal: Nov 2005
Città: TO
Messaggi: 5206
Quote:
Originariamente inviato da riemann_01
Salve a tutti!
Ho re-implementato la funzione memcpy per cercare di capirne al meglio il significato e l'utilizzo.
Codice:
// memcpy.cc

#include <iostream>
using namespace std;

void* memcpy(void* s1, const void* s2, unsigned lenght)
{
	const char* from = (const char*)s2;
	char* to = (char*)s1;
	
	while (lenght != 0) {
		*to++ = *from++;
		--lenght;
	}
	return to;
}

int main()
{
	char* src = "prova";
	char dest[strlen(src)+1];
	
	cout << "source: " << src << endl;
	char* result = (char*)memcpy(dest,src,sizeof(src)+1);  // inutile??
	cout << "destination: " << dest << endl;
}
Cio' che non riesco ad interpretare correttamente e' il tipo di ritorno. A che serve?
Il puntatore to e' automatic, quindi lo spazio di memoria riservato alla stringa in stile C viene liberato dopo l'ultima istruzione return. In che modo si potrebbe utilizzare un indirizzo iniziale di una sequenza di caratteri alfanumerici gia' deallocata?
Infatti non devi restituire il tuo to ma devi restituire s1 (che nella funzione non viene toccato).
Secondo le specifiche, memcpy deve ritornare il puntatore all'area di destinazione.
__________________
Andrea, SCJP 5 (91%) - SCWCD 5 (94%)
andbin è offline   Rispondi citando il messaggio o parte di esso
Old 30-05-2006, 11:04   #3
riemann_01
Member
 
Iscritto dal: May 2006
Messaggi: 38
Grazie per la risposta immediata. Modifico subito la funzione!
riemann_01 è offline   Rispondi citando il messaggio o parte di esso
Old 30-05-2006, 15:20   #4
sottovento
Senior Member
 
L'Avatar di sottovento
 
Iscritto dal: Nov 2005
Città: Texas
Messaggi: 1722
Ciao
il codice e' corretto. Hai pero' la possibilita' di eseguirlo piu' velocemente, a patto di complicare un po' l'algoritmo: invece di trasferire un byte alla volta, potresti trasferirne 4, ottimizzando i trasferimenti sul bus.
Ovviamente devi prestare attenzione ai resti ed agli allineamenti, ma non e' difficile.

High Flying
Sottovento
__________________
In God we trust; all others bring data
sottovento è offline   Rispondi citando il messaggio o parte di esso
Old 30-05-2006, 15:59   #5
andbin
Senior Member
 
L'Avatar di andbin
 
Iscritto dal: Nov 2005
Città: TO
Messaggi: 5206
Quote:
Originariamente inviato da sottovento
Hai pero' la possibilita' di eseguirlo piu' velocemente, a patto di complicare un po' l'algoritmo: invece di trasferire un byte alla volta, potresti trasferirne 4, ottimizzando i trasferimenti sul bus.
Beh, a questo punto uno la scrive in Assembly ...

Comunque se si volesse implementarla in modo un po' più efficiente in "C", si può fare così:
Codice:
typedef unsigned char VAL8;
typedef unsigned long VAL32;

void *my_memcpy (void *dest, const void *src, int length)
{
    register VAL32 a, b;
    VAL32 *d = (VAL32*) dest;
    VAL32 *s = (VAL32*) src;
    VAL8 *d2, *s2;

    while (length >= 8)
    {
        a = *(s+0);
        b = *(s+1);
        *(d+0) = a;
        *(d+1) = b;
        s += 2;
        d += 2;
        length -= 8;
    }

    s2 = (VAL8*) s;
    d2 = (VAL8*) d;

    while (length-- > 0)
        *d2++ = *s2++;

    return dest;
}
Ho provato a compilarlo con gcc con la massima ottimizzazione (-O3) e poi ho guardato, per curiosità, il disassemblato. Mi sembra ancora un po' sgalfo ... in puro Assembly si può sicuramente migliorare.

EDIT: Aggiunto solo = nel test.
__________________
Andrea, SCJP 5 (91%) - SCWCD 5 (94%)

Ultima modifica di andbin : 31-05-2006 alle 08:16.
andbin è offline   Rispondi citando il messaggio o parte di esso
Old 30-05-2006, 19:46   #6
71104
Bannato
 
L'Avatar di 71104
 
Iscritto dal: Feb 2005
Città: Roma
Messaggi: 7029
due cose:
1) il codice è sbagliato perché non tieni conto degli overlaps, mentre la versione originale lo fa
2) gli Intel hanno istruzioni che fanno tutto il lavoro; guarda per esempio le varie versioni di REP MOVS, credo che tengano anche conto degli overlaps
71104 è offline   Rispondi citando il messaggio o parte di esso
Old 30-05-2006, 20:52   #7
andbin
Senior Member
 
L'Avatar di andbin
 
Iscritto dal: Nov 2005
Città: TO
Messaggi: 5206
Quote:
Originariamente inviato da 71104
il codice è sbagliato perché non tieni conto degli overlaps
Appositamente non ho tenuto conto dell'overlap, per 2 motivi: (a) perché il mio codice voleva essere un semplice esempio (senza alcuna pretesa di essere perfetto o super-efficiente ) di come copiare più byte per volta in linguaggio "C" per velocizzare un pochino la copia. (b) per il motivo seguente.

Quote:
Originariamente inviato da 71104
mentre la versione originale lo fa
No, una implementazione della memcpy non è obbligata a gestire l'overlap. Ad esempio su linux il man dice:
Quote:
DESCRIPTION
The memcpy() function copies n bytes from memory area src
to memory area dest. The memory areas may not overlap.
Use memmove(3) if the memory areas do overlap.
Su alcune implementazioni potrebbe gestire l'overlap ma non è mandatorio. L'unica funzione il cui funzionamento è garantito anche con l'overlap è memmove.

Quote:
Originariamente inviato da 71104
2) gli Intel hanno istruzioni che fanno tutto il lavoro; guarda per esempio le varie versioni di REP MOVS
Vero.

Quote:
Originariamente inviato da 71104
credo che tengano anche conto degli overlaps
No, o per dire meglio "ni". Dati i due puntatori (E)SI e (E)DI, questi vengono incrementati o decrementati entrambi in base al flag DF (0=incremento, 1=decremento). Non è quindi la REP MOVS a gestire per conto suo l'overlap! Al massimo può essere l'applicazione che controlla se c'è overlap e quindi aggiusta i 2 puntatori e la direzione.
__________________
Andrea, SCJP 5 (91%) - SCWCD 5 (94%)
andbin è offline   Rispondi citando il messaggio o parte di esso
Old 31-05-2006, 01:49   #8
71104
Bannato
 
L'Avatar di 71104
 
Iscritto dal: Feb 2005
Città: Roma
Messaggi: 7029
Quote:
Originariamente inviato da andbin
Appositamente non ho tenuto conto dell'overlap, per 2 motivi: (a) perché il mio codice voleva essere un semplice esempio (senza alcuna pretesa di essere perfetto o super-efficiente ) di come copiare più byte per volta in linguaggio "C" per velocizzare un pochino la copia. (b) per il motivo seguente.
ma non mi riferivo al tuo codice in particolare, mi riferivo a tutti quelli postati finora

Quote:
No, una implementazione della memcpy non è obbligata a gestire l'overlap. Ad esempio su linux il man dice: [...]
ops, mi confondevo con memmove!

chissà perché lo standard del C prevede che la memmove gestisca gli overlap e la memcpy no...

è troppo vecchio sto linguaggio, e Unix assieme ad esso; certe cose di Unix e del C sono abbastanza strane.
71104 è offline   Rispondi citando il messaggio o parte di esso
Old 31-05-2006, 11:21   #9
riemann_01
Member
 
Iscritto dal: May 2006
Messaggi: 38
Quote:
Originariamente inviato da 71104
1) il codice è sbagliato perché non tieni conto degli overlaps, mentre la versione originale lo fa
Non e' cosi', ti confondi per come e' gia' stato riferito.
riemann_01 è offline   Rispondi citando il messaggio o parte di esso
Old 31-05-2006, 11:22   #10
riemann_01
Member
 
Iscritto dal: May 2006
Messaggi: 38
Quote:
Originariamente inviato da sottovento
Ciao
il codice e' corretto. Hai pero' la possibilita' di eseguirlo piu' velocemente, a patto di complicare un po' l'algoritmo: invece di trasferire un byte alla volta, potresti trasferirne 4, ottimizzando i trasferimenti sul bus.
Ovviamente devi prestare attenzione ai resti ed agli allineamenti, ma non e' difficile.

High Flying
Sottovento

Puoi postare il codice?
riemann_01 è offline   Rispondi citando il messaggio o parte di esso
Old 31-05-2006, 11:24   #11
andbin
Senior Member
 
L'Avatar di andbin
 
Iscritto dal: Nov 2005
Città: TO
Messaggi: 5206
Quote:
Originariamente inviato da riemann_01
Puoi postare il codice?
Ma l'ho già postato io ...
__________________
Andrea, SCJP 5 (91%) - SCWCD 5 (94%)
andbin è offline   Rispondi citando il messaggio o parte di esso
Old 31-05-2006, 12:51   #12
riemann_01
Member
 
Iscritto dal: May 2006
Messaggi: 38
Si, ma vorrei capire in che modo l'avrebbe implementato lui! Non te la prendere!
Ho studiato il tuo codice e l'ho apprezzato!

Una domanda: perche' hai usato come class-storage per a e b register?
Non viene quasi sempre ignorato dal compilatore?

Ultima modifica di riemann_01 : 31-05-2006 alle 12:55.
riemann_01 è offline   Rispondi citando il messaggio o parte di esso
Old 31-05-2006, 13:00   #13
andbin
Senior Member
 
L'Avatar di andbin
 
Iscritto dal: Nov 2005
Città: TO
Messaggi: 5206
Quote:
Originariamente inviato da riemann_01
Si, ma vorrei capire in che modo l'avrebbe implementato lui! Non te la prendere!
Ah ok, non c'è problema ... credevo che ti fosse sfuggito o non avessi visto bene il mio codice.

Quote:
Originariamente inviato da riemann_01
Una domanda: perche' hai usato come class-storage register per a e b?
Non viene quasi sempre ignorato dal compilatore?
a e b sono le variabili che tengono i valori temporanei da spostare, quindi è logico che allocarli nei registri sarebbe la cosa migliore.
Io ce l'ho messo il register ... se poi il compilatore lo ignora e se ne frega ... non ci posso fare nulla.
__________________
Andrea, SCJP 5 (91%) - SCWCD 5 (94%)
andbin è offline   Rispondi citando il messaggio o parte di esso
Old 31-05-2006, 13:06   #14
ilsensine
Senior Member
 
L'Avatar di ilsensine
 
Iscritto dal: Apr 2000
Città: Roma
Messaggi: 15625
Codice:
	char dest[strlen(src)+1];
Occhio che è fuori standard. E' accettata dal gcc, ma altri compilatori possono benissimo rifiutare questo tipo di allocazione dinamica di un array sullo stack.
Ad es. il compilatore Microsoft mi sembra che rifiuti questa sintassi.

Codice:
	char* result = (char*)memcpy(dest,src,sizeof(src)+1);
Ho il dubbio che qui la sizeof non sia quello che intendevi mettere: sizeof(src) == sizeof(void *) == 4 (oppure 8), indipendentemente dalla lunghezza della stringa puntata da src.
E' un caso se ti funziona.
__________________
0: or %edi, %ecx; adc %eax, (%edx); popf; je 0b-22; pop %ebx; fadds 0x56(%ecx); lds 0x56(%ebx), %esp; mov %al, %al
andeqs pc, r1, #147456; blpl 0xff8dd280; ldrgtb r4, [r6, #-472]; addgt r5, r8, r3, ror #12
ilsensine è offline   Rispondi citando il messaggio o parte di esso
Old 31-05-2006, 13:09   #15
riemann_01
Member
 
Iscritto dal: May 2006
Messaggi: 38
to: andbin

Un'altra domanda che mi e' venuta in mente in questo momento.
Sebbene con la tua versione si possano copiare 4 bytes per volta questo pero' comporta un incremento delle variabili locali utilizzate. Per valutare la complessita' della funzione non occorre tenere in conto anche le risorse di memorizzazione oltre che il numero di operazioni eseguite?

Ultima modifica di riemann_01 : 31-05-2006 alle 13:28.
riemann_01 è offline   Rispondi citando il messaggio o parte di esso
Old 31-05-2006, 13:26   #16
riemann_01
Member
 
Iscritto dal: May 2006
Messaggi: 38
to: sensine

E' solo un caso fortuito, in effetti, che il programma funzioni: la stringa src e' composta da cinque caratteri.

Queste modifiche dovrebbero rendere il codice privo di errori:

Codice:
char* dest = new char[strlen(src)+1];
Codice:
char* result = (char*)memcpy(dest,src,strlen(src)+1);
Se cosi' non fosse vi prego di inviarmi le vostre segnalazioni!

Grazie a tutti per il supporto!
riemann_01 è offline   Rispondi citando il messaggio o parte di esso
Old 31-05-2006, 15:50   #17
sottovento
Senior Member
 
L'Avatar di sottovento
 
Iscritto dal: Nov 2005
Città: Texas
Messaggi: 1722
Ciao a riemann_01 e a tutti gli altri
scusate la risposta un po' in ritardo, ma e' per il fuso orario.

Visto che e' stato richiesto, provo a postare una mia versione. Purtroppo non l'ho provata, ma qualche mese fa ho fatto una prova con un codice simile, per cui sono piuttosto sicuro (errori di codifica a parte) delle prove di ottimizzazione:

Codice:
void *my_memcpy (void *dst, void *src, int nbytes)
{
	register char *r_dst = (char *)dst;
	register char *r_src = (char *)src;
	int n = nbytes / 4;
	int remaining = nbytes % 4;
	register int i;
	register char *p;
	register char *q;

	for (i = n; i; --i)
		*r_dst++ = *r_src++;

	p = (char *)r_dst;
	q = (char *)r_src;
	for (i = remaining; i; --i)
		*p++ = *q++;
	
	return dst;
}
Il sistema che ho usato a provare il codice di cui parlavo e' un fratellino di pSos+ (run-to-completion, preemption a priorita' fisse, no time sharing).
Il processore e' un simil-Motorola, con un set di istruzioni quasi uguale.

Il compilatore onora le variabili registro nell'ordine in cui le trova, partendo dalle prime dichiarate e fintanto che puo'.

L'idea e' quella di fare un ciclo 4 volte piu' corto. Rispetto ad AndBin, utilizzo solo post-incrementi perche' sono andato a vedere il codice assembler generato: il processore in uso, infatti, ha una istruzione di post-incremento di registro, pertanto posso risolvere il ciclo con il minore numero di istruzioni possibile.
Esiste anche l'istruzione di pre-decremento di un registro, che quindi e' stata utilizzata per il ciclo for. Inoltre il confronto con zero e' piu' veloce, per cui il ciclo che conta al rovescio risulta piu' efficiente (sulla mia macchina, ovviamente).

Sempre sulla mia macchina, per inciso, l'istruzione
a++
e l'istruzione
a += 1
vengono risolte con un codice diverso, con il risultato che il primo e' piu' veloce del secondo.

Questa tecnica era gia' usata sui primi Macintosh con processore 680x0, visto il set di istruzioni a disposizione (e visto che era spiegata nei libri della serie "Inside Macintosh"). E' uno dei casi in cui l'implementazione C ha una rappresentazione praticamente 1 a 1 con l'assembler, pertanto la codifica in assembler non porta alcun vantaggio.

Scusate eventuali errori. A disposizione per le correzioni

High Flying
Sottovento
__________________
In God we trust; all others bring data
sottovento è offline   Rispondi citando il messaggio o parte di esso
 Rispondi


Recensione Samsung Galaxy Z Fold7: un grande salto generazionale Recensione Samsung Galaxy Z Fold7: un grande sal...
The Edge of Fate è Destiny 2.5. E questo è un problema The Edge of Fate è Destiny 2.5. E questo ...
Ryzen Threadripper 9980X e 9970X alla prova: AMD Zen 5 al massimo livello Ryzen Threadripper 9980X e 9970X alla prova: AMD...
Acer TravelMate P4 14: tanta sostanza per l'utente aziendale Acer TravelMate P4 14: tanta sostanza per l'uten...
Hisense M2 Pro: dove lo metti, sta. Mini proiettore laser 4K per il cinema ovunque Hisense M2 Pro: dove lo metti, sta. Mini proiett...
Sharkoon punta sui case a basso costo, m...
La tua rete Wi-Fi fa pena? Questi FRITZ!...
Amazon, un weekend di fuoco per gli scon...
Ancora 3 smartwatch Amazfit in forte sco...
Sharkoon A60 RGB: dissipatore ad aria du...
HONOR 400 Pro a prezzo bomba su Amazon: ...
Offerte da non perdere: robot aspirapolv...
Apple Watch e Galaxy Watch ai minimi sto...
Il rover NASA Perseverance ha ''raccolto...
NASA e ISRO hanno lanciato il satellite ...
Switch 2 ha venduto 5,82 milioni di cons...
Assassin's Creed Black Flag Remake: le m...
Cosa ci fa una Xiaomi SU7 Ultra alle por...
Promo AliExpress Choice Day: prezzi stra...
Nostalgico, ma moderno: il nuovo THEC64 ...
Chromium
GPU-Z
OCCT
LibreOffice Portable
Opera One Portable
Opera One 106
CCleaner Portable
CCleaner Standard
Cpu-Z
Driver NVIDIA GeForce 546.65 WHQL
SmartFTP
Trillian
Google Chrome Portable
Google Chrome 120
VirtualBox
Tutti gli articoli Tutte le news Tutti i download

Strumenti

Regole
Non Puoi aprire nuove discussioni
Non Puoi rispondere ai messaggi
Non Puoi allegare file
Non Puoi modificare i tuoi messaggi

Il codice vB è On
Le Faccine sono On
Il codice [IMG] è On
Il codice HTML è Off
Vai al Forum


Tutti gli orari sono GMT +1. Ora sono le: 13:57.


Powered by vBulletin® Version 3.6.4
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
Served by www3v