2009-05-05 39 views
10

La mia piattaforma è Windows Vista 32, con visual C++ express 2008.Più thread che leggono dallo stesso file

ad esempio:

se ho un file contiene 4000 byte, posso avere 4 fili leggere dal file contemporaneamente? e ogni thread accede a una sezione diversa del file.

filo 1 letto 0-999, filo 2 leggere 1000-2999, ecc

si prega di dare un esempio in linguaggio C.

+1

Suona come i compiti. Quale libreria di threading usi? Dove sei rimasto bloccato? – dirkgently

+0

non è un compito, amico, voglio solo sapere se è possibile o no. non so nemmeno come farlo, dato che la maggior parte della soluzione pubblicata su google non sembra un vero file di accesso parallelo, tutti usano i blocchi – anru

risposta

20

Se non si scrive su di essi, non è necessario occuparsi delle condizioni di sincronizzazione/gara.

Basta aprire il file con lettura condivisa come maniglie diverse e tutto funzionerebbe. (Ad esempio, è necessario aprire il file nel contesto del thread anziché condividere lo stesso handle di file).

#include <stdio.h> 
#include <windows.h> 

DWORD WINAPI mythread(LPVOID param) 
{ 
    int i = (int) param; 
    BYTE buf[1000]; 
    DWORD numread; 

    HANDLE h = CreateFile("c:\\test.txt", GENERIC_READ, FILE_SHARE_READ, 
     NULL, OPEN_EXISTING, 0, NULL); 

    SetFilePointer(h, i * 1000, NULL, FILE_BEGIN); 
    ReadFile(h, buf, sizeof(buf), &numread, NULL); 
    printf("buf[%d]: %02X %02X %02X\n", i+1, buf[0], buf[1], buf[2]); 

    return 0; 
} 

int main() 
{ 
    int i; 
    HANDLE h[4]; 

    for (i = 0; i < 4; i++) 
     h[i] = CreateThread(NULL, 0, mythread, (LPVOID)i, 0, NULL); 

    // for (i = 0; i < 4; i++) WaitForSingleObject(h[i], INFINITE); 
    WaitForMultipleObjects(4, h, TRUE, INFINITE); 

    return 0; 
} 
+1

Il ciclo con WaitForSingleObject() deve essere sostituito con una singola chiamata WaitForMultipleObjects(). Oltre a questo è +1. – mghie

2

È possibile avere più thread che leggono da una struttura di dati, le condizioni di gara possono potenzialmente verificarsi se qualsiasi scrittura sta avvenendo.

Per evitare tali condizioni di gara è necessario definire i limiti che i thread possono leggere, se si dispone di un numero esplicito di segmenti di dati e un numero esplicito di thread per abbinarli, è facile.

Come per un esempio in C, è necessario fornire ulteriori informazioni, ad esempio la libreria di threading che si sta utilizzando. Provalo prima, quindi possiamo aiutarti a risolvere eventuali problemi.

+0

non ho ancora scritto il programma, ma proverò pthread, dato che ho fatto qualche pthread lavoro in Linux. il programma non scriverà nulla, solo bisogno di leggere dal file. – anru

-1

È necessario un modo per sincronizzare tali thread. Esistono diverse soluzioni per mutex http://en.wikipedia.org/wiki/Mutual_exclusion

+0

se sincronizzo quei thread, quindi non sta leggendo il file allo stesso tempo, diventa una lettura in sequenza, giusto? – anru

+0

Proprio se quel file non verrà scritto da altri thread/socket. Se nel tuo caso vuoi solo leggere ma da parti diverse, perché non analizzare l'intero file una volta prima nei 4 vars di cui hai bisogno? – ktulur

-1

Vuole leggere da un file in thread diversi. Immagino che dovrebbe essere ok se il file è aperto in sola lettura da ogni thread.

Spero che non vogliate fare questo per prestazioni, dato che dovrete analizzare ampie parti del file per i caratteri newline in ogni thread.

+0

perché è necessario cercare il nuovo carattere di linea? – anru

+0

devi sapere a quale offset nella riga di file 1000, 2000, 3000 e così via, inizia. – Jonatan

+0

sta accedendo ai byte, non alle linee, quindi non c'è bisogno di preoccuparsene. – Francis

0

Non dovresti fare nulla di particolarmente intelligente se tutto quello che stanno facendo è leggere. Ovviamente puoi leggerlo tutte le volte che vuoi in parallelo, a patto che non lo blocchi esclusivamente. Scrivere è chiaramente un'altra questione ...

Devo chiedermi il motivo per cui vorresti farlo - probabilmente funzionerà male dato che il tuo HDD sprecherà molto tempo a cercare avanti e indietro piuttosto che leggerlo tutto in una (relativamente) spazzata ininterrotta. Per i file di piccole dimensioni (come il tuo esempio di 4000 righe), dove questo potrebbe non essere un problema, non sembra valere la pena.

+0

A seconda del tipo di unità, è possibile ottenere prestazioni migliori, ad esempio con una (buona) unità a stato solido che fornirà buone prestazioni multi-thread. –

+0

Come non bloccare il file esclusivamente e leggere da esso? –

2

Non vedo alcun reale vantaggio nel fare ciò.
È possibile che più thread vengano letti dal dispositivo, ma il collo di bottiglia non sarà la CPU, ma piuttosto la velocità IO del disco.

Se non si presta attenzione, è possibile che anche i processi vengano rallentati (ma è necessario misurarlo per accertarsi con certezza).

+1

Se ha un buon raid o un SSD, questo potrebbe non essere così male, ma un buon punto. +1 –

+0

Un buon punto, ma sarebbe particolarmente utile se il costo di elaborazione di una linea supera il costo dell'accesso al disco ... –

0

È possibile anche se non sono sicuro che ne varrà la pena. Hai considerato di leggere l'intero file in memoria all'interno di un singolo thread e quindi consentire a più thread di accedere a quei dati?

0

Lettura: non è necessario bloccare il file. È sufficiente aprire il file in sola lettura o condiviso.

Scrittura: utilizzare un mutex per garantire che il file venga scritto solo da una persona.

0

Come altri hanno già notato, non vi è alcun problema intrinseco nell'avere più thread letti dallo stesso file, purché abbiano il proprio descrittore/handle di file. Tuttavia, sono un po 'curioso dei tuoi motivi . Perché vuoi leggere un file in parallelo? Se stai leggendo un file solo in memoria, il tuo collo di bottiglia è probabilmente il disco stesso, nel qual caso thread multipli non ti aiuteranno affatto (faranno solo confusione nel codice).

E come sempre quando si ottimizza, non si dovrebbe tentare fino a che (1) non si ha una soluzione facile da capire, funzionante, e (2) si è misurato il codice per sapere dove si dovrebbe ottimizzare.

+0

Questo codice per leggere linee specifiche da un file funziona in thread diversi? Leggendo lo stesso file e più righe ciascuno? Http: //rosettacode.org/wiki/Read_a_specific_line_from_a_file#C –

4

Non c'è nemmeno un grosso problema scrivendo allo stesso file, in tutta onestà.

Di gran lunga il modo più semplice è semplicemente la mappatura della memoria del file. Il sistema operativo ti fornirà quindi un void * dove il file è mappato in memoria. Trasmettetelo in un carattere [] e assicuratevi che ogni thread utilizzi i sottaraggi non sovrapposti.

void foo(char* begin, char*end) { /* .... */ } 
void* base_address = myOS_memory_map("example.binary"); 
myOS_start_thread(&foo, (char*)base_address, (char*)base_address + 1000); 
myOS_start_thread(&foo, (char*)base_address+1000, (char*)base_address + 2000); 
myOS_start_thread(&foo, (char*)base_address+2000, (char*)base_address + 3000); 
+0

Quali sono queste funzioni che stai utilizzando? myOS_start_thread e myOS_memory_map? Non riesco a trovarli in linguaggio c? e gentilmente spiega la tua risposta in modo più semplice? grazie –

+1

@FarazAhmad: Questo perché sono nomi intenzionalmente falsi. Sostituisci con qualsiasi sistema operativo utilizzi. Inoltre, la risposta è precedente al C++ 11, quindi non ho potuto usare 'std :: thread'. – MSalters

2

Windows supporta I sovrapposto/O, che consente a un singolo thread di coda in modo asincrono più richieste di I/O per migliorare le prestazioni. Questo potrebbe verosimilmente essere utilizzato da più thread simultaneamente finché il file che si sta accedendo cerca di supporto (cioè questa non è una pipe).

Il passaggio da FILE_FLAG_OVERLAPPED a CreateFile() consente di leggere e scrivere contemporaneamente sullo stesso handle di file; altrimenti, Windows li serializza. Specificare l'offset del file utilizzando i membri Offset e OffsetHigh della struttura OVERLAPPED.

Per ulteriori informazioni, vedere Synchronization and Overlapped Input and Output.

1

Il modo più semplice è aprire il file all'interno di ogni istanza parallela, ma è sufficiente aprirlo come readonly.

Le persone che dicono che ci può essere un collo di bottiglia di IO probabilmente non hanno ragione. Qualsiasi sistema operativo moderno memorizza nella cache le letture dei file. Il che significa che la prima volta che leggerai un file sarà la più lenta e tutte le letture successive saranno velocissime. Un file di 4000 byte può persino riposare nella cache del processore.

0
std::mutex mtx; 

void worker(int n) 
{ 
    mtx.lock(); 

    char * memblock; 

    ifstream file ("D:\\test.txt", ios::in); 

    if (file.is_open()) 
    { 
     memblock = new char [1000]; 
     file.seekg (n * 999, ios::beg); 
     file.read (memblock, 999); 
     memblock[999] = '\0'; 

     cout << memblock << endl; 

     file.close(); 
     delete[] memblock; 
    } 
    else 
     cout << "Unable to open file"; 
    mtx.unlock(); 
} 


int main() 
{ 
    vector<std::thread> vec; 
    for(int i=0; i < 3; i++) 
    { 
     vec.push_back(std::thread(&worker,i)); 
    } 

    std::for_each(vec.begin(), vec.end(), [](std::thread& th) 
    { 
     th.join(); 
    }); 
    return 0; 
} 
Problemi correlati