Come impostare lo stacksize con C ++ 11 std :: thread

Ho cercato di familiarizzare con la libreria std :: thread in C ++ 11 e sono arrivato a un ostacolo.

Inizialmente provengo da uno sfondo di thread posix, e mi chiedevo come si configura la dimensione dello stack di std :: thread prima della costruzione, dato che non riesco a trovare alcun riferimento all’esecuzione di tale attività.

L’uso di pthreads che impostano le dimensioni dello stack è fatto in questo modo:

void* foo(void* arg); . . . . pthread_attr_t attribute; pthread_t thread; pthread_attr_init(&attribute); pthread_attr_setstacksize(&attribute,1024); pthread_create(&thread,&attribute,foo,0); pthread_join(thread,0); 

C’è qualcosa di simile quando usi std :: thread ?

Sto usando il seguente riferimento:

http://en.cppreference.com/w/cpp/thread

Inizialmente provengo da uno sfondo di thread posix, e mi chiedevo come si configura la dimensione dello stack di std :: thread prima della costruzione, dato che non riesco a trovare alcun riferimento all’esecuzione di tale attività.

Non puoi std::thread non supporta questo perché std::thread è standardizzato, e C ++ non richiede che una macchina abbia anche uno stack, tanto meno uno fisso.

i pthreads sono più restrittivi in ​​termini di hardware che supportano e presuppone che ci sia una certa dimensione di stack fissa per thread. (Quindi puoi configurare questo)

Come già detto da Loki Astari, è estremamente raro avere effettivamente bisogno di uno stack non predefinito e di solito è un errore o il risultato di una ctriggers programmazione.

  • Se ritieni che la dimensione dello stack predefinita sia troppo grande per le tue esigenze e desideri ridurla, dimenticala. Ogni sistema operativo moderno ora utilizza la memoria virtuale / commit su richiesta, il che significa che la memoria è riservata, non effettivamente allocata, finché non si accede alle pagine. Ridurre le dimensioni dello stack non ridurrà il tuo attuale ingombro di memoria.

  • A causa di questo comportamento, i sistemi operativi possono permettersi di impostare la dimensione dello stack predefinita su valori molto grandi. Ad esempio su un Debian vanilla questo è 8MB ( ulimit -s ) che dovrebbe essere sufficiente per ogni esigenza. Se riesci ancora a raggiungere questo limite, la mia prima idea sarebbe che il tuo codice sia sbagliato, quindi dovresti prima di tutto rivederlo e spostare le cose nell’heap, trasformare le funzioni ricorsive in loop, ecc.

  • Se nonostante tutto questo hai davvero bisogno di cambiare le dimensioni dello stack (es. Aumentarlo, dato che ridurlo è inutile), su POSIX puoi sempre usare setrlimit all’inizio del tuo programma per aumentare la dimensione dello stack di default. Sicuramente questo avrà effetto su tutti i thread, ma solo quelli che ne hanno bisogno utilizzeranno effettivamente la memoria aggiuntiva.

  • Ultimo ma non meno importante, in tutta onestà posso vedere un caso d’angolo in cui la riduzione delle dimensioni dello stack avrebbe senso: se si hanno tonnellate di thread su un sistema a 32 bit, potrebbero consumare lo spazio dell’indirizzo virtuale (di nuovo, non la memoria effettiva consumo) fino al punto in cui non si dispone di sufficiente spazio di indirizzamento disponibile per l’heap. Ancora una volta, setrlimit è tuo amico qui, anche se consiglierei di passare a un sistema a 64 bit per beneficiare dello spazio di indirizzi virtuali più grande (e se il tuo programma è così grande, probabilmente beneficerai anche della RAM aggiuntiva).

Ho trovato questo nel libro di Scott Meyers Overview of the New C++(C++0x) , visto che è piuttosto lungo non riesco a postarlo come commento, è utile?

Esiste anche un’API standard per accedere agli handle specifici della piattaforma dietro thread, mutex, variabili di condizione, ecc. Si presume che questi handle siano il meccanismo per l’impostazione delle priorità dei thread, l’impostazione delle dimensioni dello stack, ecc. (Per quanto riguarda l’impostazione delle dimensioni dello stack, Anthony Williams nota: “Tra quei sistemi operativi che supportano l’impostazione delle dimensioni dello stack, tutti lo fanno in modo diverso: se si sta codificando per una piattaforma specifica (in modo che l’uso di native_handle sia OK), è ansible utilizzare le funzionalità di tale piattaforma per per esempio in POSIX è ansible utilizzare makecontext e swapcontext insieme all’assegnazione esplicita di uno stack e su Windows è ansible utilizzare Fibers.Potrebbero quindi utilizzare le funzionalità specifiche della piattaforma (ad esempio flag Linker) per impostare le dimensioni di stack predefinite su qualcosa davvero minuscolo, e quindi passare gli stack a qualcosa di più grande dove necessario. “)

Ho anche indagato su questo problema. Per alcune applicazioni, la dimensione dello stack predefinita non è adeguata. Esempi: il programma fa una ricorsione profonda dipendente dal problema specifico che sta risolvendo; il programma deve creare molti thread e il consumo di memoria è un problema.

Ecco un riepilogo delle soluzioni / soluzioni (parziali) che ho trovato:

  • g ++ supporta l’opzione -fsplit-stack su Linux. Vedi per maggiori informazioni sugli stack Split. Ecco il riassunto dal loro sito web:

L’objective degli stack divisi è quello di permettere uno stack non contiguo che viene cresciuto automaticamente secondo necessità. Ciò significa che è ansible eseguire più thread, ciascuno a partire da un piccolo stack, e fare in modo che lo stack aumenti e si riduca a seconda del programma.

Nota: -fsplit-stack funzionato solo per me dopo che ho iniziato a utilizzare il linker oro . Sembra che clang ++ supporti anche questa bandiera. La versione che ho provato (clang ++ 3.3) si è -fsplit-stack durante il tentativo di compilare la mia applicazione utilizzando il flag -fsplit-stack .

  • Su Linux, imposta le dimensioni dello stack eseguendo ulimit -s prima di avviare l’applicazione. size è la size dello stack in Kbs. Osservazione: il comando unlimit -s unlimited non ha influito sulla dimensione dei thread creati con std::thread . Quando ho usato ulimit -s unlimited , il thread principale potrebbe crescere, ma i thread creati con std::thread avevano le dimensioni predefinite.

  • Su Windows utilizzando Visual Studio, possiamo usare il parametro linker /STACK o /STACKSIZE nel file di definizione del modulo, questa è la dimensione predefinita per tutti i thread creati. Vedi questo link per maggiori informazioni. Possiamo anche modificare questo parametro in qualsiasi eseguibile usando lo strumento da riga di comando EDITBIN .

  • Su Windows usando mingw g ++, possiamo usare l’opzione -Wl,--stack, . Per qualche ragione, quando si usa cygwin g ++, questo flag influenza solo la dimensione del thread principale.

Approcci che non hanno funzionato per me:

  • ulimit -s su OSX. Influisce solo sulla dimensione del thread principale. Inoltre, l’impostazione predefinita di Mac OSX per le dimensioni di un pthread stack è 512 kB.

  • setrlimit influenza solo la dimensione del thread principale su Linux e OSX. Su cygwin, non ha mai funzionato per me, sembra che restituisca sempre un errore.

Per OSX, l’unica alternativa sembra usare boost::thread invece di std::thread , ma questo non è bello se vogliamo attenerci allo standard. Spero che g ++ e clang ++ supportino anche -fsplit-stack su OSX in futuro.

Stavo cercando la risposta a questo io solo ora.

Sembra che mentre std :: thread non supporta questo, boost :: thread fa.

In particolare, è ansible utilizzare boost :: thread :: attributes per ottenere ciò:

 boost::thread::attributes attrs; attrs.set_size(4096*10); boost::thread myThread(attrs, fooFunction, 42);