Pergunta

Eu tenho pequena, mas frequentemente utilizados objetos de função.Cada thread obtém a sua própria cópia.Tudo é alocado estaticamente.Cópias não partilhar quaisquer dados globais ou estáticos.Eu preciso proteger esta objetos de falso compartilhamento?

Obrigado.EDITAR:Aqui é um brinquedo programa que usa o Boost.Threads.Pode falso compartilhamento ocorrer para o campo dados?

#include <boost/thread/thread.hpp>

struct Work {
    void operator()() {
        ++data;
    }

    int data;
};

int main() {
    boost::thread_group threads;
    for (int i = 0; i < 10; ++i)
        threads.create_thread(Work());
    threads.join_all();
}
Foi útil?

Solução

Falso compartilhamento entre threads é quando 2 ou mais threads utilizam a mesma linha de cache.

E. g.:

struct Work {
    Work( int& d) : data( d ) {}
    void operator()() {
        ++data;
    }

    int& data;
};

int main() {
    int false_sharing[10] = { 0 };
    boost::thread_group threads;
    for (int i = 0; i < 10; ++i)
        threads.create_thread(Work(false_sharing[i]));
    threads.join_all();

    int no_false_sharing[10 * CACHELINE_SIZE_INTS] = { 0 };
    for (int i = 0; i < 10; ++i)
        threads.create_thread(Work(no_false_sharing[i * CACHELINE_SIZE_INTS]));
    threads.join_all();
}

Os threads no primeiro bloco, sofrem falso compartilhamento.Os threads no segundo bloco não (graças a CACHELINE_SIZE).

Dados na pilha é sempre "agora" longe de outros segmentos.(E. g.no windows, pelo menos, um par de páginas).

Com a sua definição de um objeto de função, falso compartilhamento pode aparecer, porque as instâncias de Work criados na pilha e este espaço de pilha é usado dentro do segmento.

Isso pode levar a vários Work instâncias de ser adjacentes e assim podem incorrer compartilhamento de linhas de cache.

Mas ...o seu exemplo não faz sentido, porque os dados nunca é tocado fora e tão falso compartilhamento é induzida desnecessariamente.

A maneira mais fácil, para evitar problemas como este, é para copiar 'compartilhado' dados localmente no tho a pilha e, em seguida, trabalhar na pilha de cópia.Quando terminar seu trabalho de copiar de volta para a saída var.

E. g:

struct Work {
    Work( int& d) : data( d ) {}
    void operator()()
    {
        int tmp = data;
        for( int i = 0; i < lengthy_op; ++i )
           ++tmp;
        data = tmp;
    }

    int& data;
};

Isso impede que todos os problemas com o compartilhamento.

Outras dicas

Eu fiz um pouco de pesquisa e parece que não há bala de prata solução para false partilha.Aqui está o que eu descobri (graças a Christopher):1) Pad seus dados de ambos os lados com não utilizados ou utilizados com menos frequência coisas.2) Copie os seus dados na pilha e copiá-lo de volta depois de todo o trabalho duro é feito.3) o Uso de cache alinhado a alocação de memória.

Eu', não se sente totalmente seguro com os detalhes, mas aqui está a minha opinião:

(1) O exemplo simplificado é quebrado desde aumentar create_thread espera de uma referência, você pode passar um temporário.

(2) se você não quiser usar vector<Work> com um item para cada thread, ou othrwise tê-los na memória sequencialmente, falso compartilhamento irá ocorrer.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top