2017-02-17 4 views
0

У меня есть два кода и на моем рабочем столе 32 ядра.Почему атомная операция выполняется быстрее, используя отдельные потоки?

код А использует 32 потоков и выполняет следующие вещи,

1) записать значения в некоторых случайных местах в памяти 2) атомарно добавить значение глобальной переменной.

В коде B используются 16 потоков для записи значений в случайные местоположения и используются еще 16 потоков для атомарного добавления значения в глобальную переменную.

Мне было интересно, почему код B быстрее с точки зрения того, сколько атомных операций выполняется в секунду для глобальной переменной.

Вот код

var a uint64 = 0 

const N = 10 * 1024 * 1024 

var data [N]uint64 

func main() { 

    for i := 0; i < 32; i ++ { 
     go func(id int) { 
      source := rand.NewSource(int64(id)) 
      local_rand := rand.New(source) 
      for { 
       atomic.AddUint64(&a, uint64(1)) 
       data[local_rand.Int31n(N)] = uint64(1) 
      } 
     }(i) 

    } 

    var b uint64 = 0 

    for { 
     c := atomic.LoadUint64(&a) 

     fmt.Println(c - b) 
     b = c 
     time.Sleep(time.Second) 
    } 

} 

Вот код В

var a uint64 = 0 

const N = 10 * 1024 * 1024 

var data [N]uint64 

func main() { 

    for i := 0; i < 16; i ++ { 
     go func(id int) { 
      source := rand.NewSource(int64(id)) 
      local_rand := rand.New(source) 
      for { 
       data[local_rand.Int31n(N)] = uint64(1) 
      } 
     }(i) 

    } 
    for i := 0; i < 16; i++ { 

     go func() { 
      for { 
       atomic.AddUint64(&a, uint64(1)) 
      } 

     }() 
    } 
    var b uint64 = 0 

    for { 
     c := atomic.LoadUint64(&a) 

     fmt.Println(c - b) 
     b = c 
     time.Sleep(time.Second) 
    } 

} 

ответ

1

атомарные операции стоят дорого. Чтобы сохранить атомарность, вам необходимо обеспечить взаимное исключение для этого блока кода. Обычно это достигается с помощью инструкций, таких как load-linked, store-conditional и т. Д. В вашем коде A у вас есть 32 атомарных операции, но в коде B вы получаете только 16. Меньше атомной работы, сократили время выполнения!

В качестве эксперимента попробуйте изменить порядок атомных операций с операцией памяти в коде A. (Сначала выполните сначала память и затем атомную). Вы должны увидеть сокращение времени выполнения.

+0

Я не думаю, что изменение количества потоков до 16 в коде A улучшает производительность. – luyi0619

+0

Я не вижу никакой разницы в том, что вы предложили. Сначала память, затем атомичность. Я что-то пропустил? – luyi0619

+0

Если у вас есть все потоки, делающие атомарные сначала, все они будут бороться за блокировку. Если у вас есть память в первую очередь, все они будут делать память сначала, однако из-за того, что кэшируется или нет, операция памяти будет завершена в разное время. Это означает, что атомные операции начнутся в разное время. Таким образом, у вас не будет такого же мнения, что и раньше. Поэтому я ожидал меньше времени выполнения. Может быть, все ваши данные кэшированы, а не то, что я ожидал. Во всяком случае, это просто теория, которая перешла мне на ум. –

Смежные вопросы