Bonjour,
j'utilise pour le moment fopen fread et fgetc pour lire des fichiers tga sur mon disque dur.
Existe-il quelque chose de plus rapide ?
merci.
Bonjour,
j'utilise pour le moment fopen fread et fgetc pour lire des fichiers tga sur mon disque dur.
Existe-il quelque chose de plus rapide ?
merci.
Bonjour,
Sous Windows, les fonctions standard du C ne sont que des wrappers autour des API systèmes. Ces wrappers sont un peu plus "gros" que les fonctions de l'API, on peut donc utiliser ces dernières mais le gain de temps est vraiment minime...j'utilise pour le moment fopen fread et fgetc pour lire des fichiers tga sur mon disque dur.
Existe-il quelque chose de plus rapide ?
Equivalences :
fopen = CreateFile() ou OpenFile()
fread = ReadFile()
fgetc = ReadFile() mais en ne lisant qu'un seul octet.
On peut techniquement "descendre" plus bas que CreateFile() avec NtCreateFile() mais c'est peu conseillé (On gagne un gros paquet de ligne de code au prix d'aucune vérification sur les paramètres). Voir MSDN : http://msdn2.microsoft.com/en-us/library/ms805591.aspx
Même chose avec ReadFile() et sa contrepartie non documentée, NtReadFile(). Voir : http://undocumented.ntinternals.net/...tReadFile.html
Mais en utilisant les APIs système tu perds la portabilité du code source...
Pour rester en C standard, tu peux lire d'un seul coup ton fichier (plutôt qu'octet par octet avec fgetc() ) en récupérant d'abord la taille de celui ci et en passant cette dernière à fread(). Voir la FAQ C :
http://c.developpez.com/faq/c/?page=...HIERS_filesize
salut,
merci pour ta reponse.
Effectivement, en lisant le fichier d'un coup et en traitant les donnees selon le format plus loin, j'obtient des resultats bien meilleurs.
Pour le moment ça m'ira merci.
Bonjour,
J'aimerai essayer le mode FILE_FLAG_NO_BUFFERING mais
1- J'ai du mal avec les contraintes demandees
2- Les sources que je trouve sont tellement indigestes que ça m'ecoeure...
bref j'aurai besoin d'un coup de pouce pour l'alignement notamment
Bonjour,
C'est vrai que ça n'est pas forcément évident, mais la documentation est assez explicite.J'ai du mal avec les contraintes demandees
Cela indique que toute tentative d'accès (aussi bien en écriture et en lecture) soit se faire obligatoirement sur un multiple de la taille du secteur.File access must begin at byte offsets within a file that are integer multiples of the volume sector size.
Par exemple, si tu souhaites lire à partir du 524ème octet de ton fichier et que la taille de secteur du volume où est situé ton fichier est de 512 octets, tu dois commencer au 512ème.
Tu récupère la taille du secteur du volume avec GetDiskFreeSpace(), ce qui nous intéresse dans le cas présent est le membre lpBytesPerSector.
cf. http://msdn2.microsoft.com/en-us/library/aa364935.aspx
Note que la version étendue "GetDiskFreeSpaceEx()" ne donne pas cette information.
Toute tentative de lecture et/ou écriture doit se faire sur un nombre d'octets égale ou multiple de la taille de secteur du volume où est situé le fichier. En d'autres termes, pour reprendre l'exemple précédent :File access must be for numbers of bytes that are integer multiples of the volume sector size. For example, if the sector size is 512 bytes, an application can request reads and writes of 512, 1024, 1536, or 2048 bytes, but not of 335, 981, or 7171 bytes.
Tu souhaites lire 2000 octets à partir du 524ème octet de ton fichier =>
Tu commence à lire à partir du 512ème octet et tu lis 2048 octets (2048 étant un multiple de 512). C'est la taille de la lecture ou de l'écriture qui importe ici.
L'adresse du tampon pour la lecture ou l'écriture doit être aligné sur un multiple de la taille du secteur. Comme le dit la MSDN, VirtualAlloc() fait cela automatiquement, pas besoin de s'en préoccuper.Buffer addresses for read and write operations should be sector aligned, which means aligned on addresses in memory that are integer multiples of the volume sector size. Depending on the disk, this requirement may not be enforced.
Exemple :
Supposons que tu veuilles lire un fichier depuis le 500ème octet et sur 2000 octets. Le taille de secteur est de 512.
Le pointeur de fichier devra être aligné sur un multiple de 512. Comme 500 est inférieur à 512. On aligne le pointeur sur 0.
Comme tu veux lire 2000 octets, mais que le pointeur de fichier est en 0, il faut allouer :
- 500 + 2000 : 2500 octets
Mais comme il faut aligner sur une taille de secteur on alloue au premier multiple de 512 supérieur à 2500, soit : 2560.
Ensuite tu peux te déplacer comme tu veux sur le tampon, seul la lecture et/ou l'écriture depuis le fichier doivent être alignées !
Voilà un exemple et qques fonction utiles sorties d'un projet (j'ai enlevé la gestion d'erreur et tout ce qui n'était pas nécessaire pour éviter un code trop lourd).
Code c : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138 #include <windows.h> #include <stdio.h> DWORD GetSectorSize (char* volume); DWORD AlignAllocSizeOnSectorSize(DWORD NumberOfBytesRequested, DWORD SectorSize); DWORD SetFilePointerFromFileStart (HANDLE hFile, DWORD FirstByte, DWORD SectorSize); DWORD GetAllocSize(DWORD FirstByteToRead, DWORD FilePointerLoc, DWORD AllocSize, DWORD SectorSize); int main (void) { HANDLE hFile; /* Handle fichier */ DWORD FilePointerLocation; /* offset pointeur de fichier */ DWORD AllocSize = 2000; /* Taille demande d'allocation */ DWORD FirstByte = 500; /* Premier octet à lire ou écrire */ DWORD TotalAlloc; /* Allocation totale */ DWORD SectorSize; /* taille secteur */ PCHAR pBuff; /* pointer buffer */ DWORD NOBR; /* nombre d'octet lu */ /* Ouverture du fichier */ hFile = CreateFile("E:\\TestData.bin", GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_NO_BUFFERING, NULL); /* récup taille secteur */ SectorSize = GetSectorSize("E:\\"); fprintf(stdout, "Sector Size : %lu\n", SectorSize); /* aligne le pointeur de fichier */ FilePointerLocation = SetFilePointerFromFileStart(hFile, FirstByte, SectorSize); fprintf(stdout, "Pointeur de fichier en : %lu\n", FilePointerLocation); /* récup taille d'allocation totale nécessaire */ TotalAlloc = GetAllocSize(FirstByte, FilePointerLocation, AllocSize, SectorSize); fprintf(stdout, "Taille totale allouée : %lu\n", TotalAlloc); /* allocation buffer */ pBuff = VirtualAlloc(NULL, TotalAlloc, MEM_COMMIT, PAGE_READWRITE); /* lecture fichier */ ReadFile(hFile, pBuff, TotalAlloc, &NOBR, NULL); /* clean up buffers & handles */ CloseHandle(hFile); VirtualFree(pBuff, 0, MEM_RELEASE); return 0; } /* * GetSectorSize * * OP : Retoune la taille de secteur pour un volume donné. * * [IN] Volume : nom du volume. * * Return : Taille de secteur pour [IN]Volume. */ DWORD GetSectorSize (char* Volume) { /* variables pour GetDiskFreeSpace */ DWORD SectorsPerCluster, BytesPerSector, NumberOfFreeClusters, TotalNumberOfClusters; /* récupère la taille d'un secteur, seul BytesPerSector nous intéresse réellement */ GetDiskFreeSpace(Volume, &SectorsPerCluster, &BytesPerSector, &NumberOfFreeClusters, &TotalNumberOfClusters); return BytesPerSector; } /* * SetFilePointerFromFileStart * * OP : Aligne le pointeur de fichier sur la taille de secteur en tenant compte du premier octet à lire ou écrire. * * [IN] hFile : Handle du fichier. * [IN] FirsByte : Premier octet à lire ou écrire. * [IN] SectorSize : Taille de secteur. * * Return : La position actuelle du pointeur de fichier après alignement. */ DWORD SetFilePointerFromFileStart (HANDLE hFile, DWORD FirstByte, DWORD SectorSize) { DWORD FilePointerLoc; FilePointerLoc = (FirstByte / SectorSize) * SectorSize; SetFilePointer(hFile, FilePointerLoc, NULL, FILE_BEGIN); return FilePointerLoc; } /* * GetAllocSize * * OP : Retourne la taille totale d'allocation du tampon en cas d'alignement strict nécessaire (CreateFile + FILE_FLAG_NO_BUFFERING) * * [IN] FirstByte : Offset du premier octet à lire ou écrire. * [IN] FilePointerLoc : Offset du pointeur de fichier [doit être aligné par la fonction SetFilePointerFromFileStart()] * [IN] AllocSize : Nombre d'otcet à allouer. * [IN] SectorSize : Taille de secteur du volume où est situé le fichier qui sera lu ou écrit. * * Return : Taille totale d'allocation. */ DWORD GetAllocSize(DWORD FirstByte, DWORD FilePointerLoc, DWORD AllocSize, DWORD SectorSize) { DWORD LastByteToReach; DWORD TotalAlloc; LastByteToReach = FirstByte + AllocSize; TotalAlloc = LastByteToReach - FilePointerLoc; return AlignAllocSizeOnSectorSize(TotalAlloc, SectorSize); } /* * AlignAllocSizeOnSectorSize * * OP : Retourne une taille d'allocation alignée sur la taille de secteur d'un volume. * * [IN] NumberOfBytesRequested : Nombre d'octets requis pour l'allocation du tampon. * [IN] SectorSize : Taille de secteur d'un volume. * * Return : La taille d'allocation alignée sur la taille de secteur. */ DWORD AlignAllocSizeOnSectorSize(DWORD NumberOfBytesRequested, DWORD SectorSize) { DWORD NumberOfSectorNeeded; DWORD Rem; NumberOfSectorNeeded = NumberOfBytesRequested / SectorSize; Rem = NumberOfBytesRequested % SectorSize; if (Rem != 0) NumberOfSectorNeeded++; return NumberOfSectorNeeded * SectorSize; }
Déjà je tiens à te remercier d'avoir passé du temps à faire une réponse si détaillée dans le soucis d'être compris. Je ne peux qu'apprécier
Le principe, comme tu le dis, est clair mais l'implementation n'est pas triviale (au moins pour moi).
Par example, je ne m'étais jamais servi de VirtualAlloc, car je ne comprend toujours pas la nuance avec un malloc. (malgré avoir lu la msdn) Le fait que l'allocation se fasse alignée n'est qu'un side effect j'imagine, il doit y avoir d'autres differences.
Merci aussi pour le code qui a l'air tres clair; si j'ai des questions dessus je te dirai.
Sinon, vois-tu des gains de performances notables avec l'utilisation d'un tel attribut ? Les tests pour assurer les contraintes de lectures ne réduisent-ils pas trop l'interret sur des fichiers de 6 - 8 mo environ ?
Et autre question hors sujet : diviser la lecture d'un même gros fichier en plusieurs semi-lectures effectuees par autant de thread differents sur un dual core voire quatri core, a pour effet de plutot allonger le temps total de lecture ou de le reduire ?
C'est vraiment dépendant de ce que tu fais sur le(s) fichier(s)... En fait mieux vaut réaliser des tests de vitesse d'exécution pour voir quelle solution est la plus profitable dans ton cas.Sinon, vois-tu des gains de performances notables avec l'utilisation d'un tel attribut ? Les tests pour assurer les contraintes de lectures ne réduisent-ils pas trop l'interret sur des fichiers de 6 - 8 mo environ ?
Les systèmes SMP aiment le threading Dès que tu as plusieurs Cores, il faut penser à la possibilité d'une implémentation multi-thread qui reduira fortement le temps de traitement.diviser la lecture d'un même gros fichier en plusieurs semi-lectures effectuees par autant de thread differents sur un dual core voire quatri core, a pour effet de plutot allonger le temps total de lecture ou de le reduire ?
Mais ça induit des problèmes, par exemple les accès concurrents sur une même ressource.
J'ai implementé cette methode dans mon projet mais le gain de vitesse reste limite environ 0.5 fps sur des fichiers image tga 24bits non compressés de 6mo 1920*1080.
C'est toujours ça de gagné.
En fait mon appli est deja multithread, mais seulement pour des operations qui travaillent sur la memoire du style "décodage en temps reel de l'image" avant l'affichageLes systèmes SMP aiment le threading Dès que tu as plusieurs Cores, il faut penser à la possibilité d'une implémentation multi-thread qui reduira fortement le temps de traitement.
Mais ça induit des problèmes, par exemple les accès concurrents sur une même ressource.
Dans le cas de lecture physique sur disque, est-il vraiment bon de faire du multithreading ? Car les tetes de lectures doivent bouger sans arret non ? dans le cas de la lecture d'un même fichier par plusieurs threads, elles ne doivent pas pouvoir acceder en même temps aux donnees si ?
Vous avez un bloqueur de publicités installé.
Le Club Developpez.com n'affiche que des publicités IT, discrètes et non intrusives.
Afin que nous puissions continuer à vous fournir gratuitement du contenu de qualité, merci de nous soutenir en désactivant votre bloqueur de publicités sur Developpez.com.
Partager