Почему классы как BindingList или ObservableCollection не ориентированы на многопотоковое исполнение?

Если вы ищете производительность, вы также можете использовать np.einsum , предположительно быстрее, чем на самом деле с помощью np.sum или np.mean. Таким образом, желаемый результат можно получить так же -

X - np.einsum('ij->i',X)[:,None]/X.shape[1]

Обратите внимание, что часть [:,None] похожа на keepdims, чтобы сохранить ее размеры так же, как у входного массива.

Тест времени выполнения

1) Сравнение только вычисления mean -

In [47]: X = np.random.rand(500, 1000)

In [48]: %timeit X.mean(axis=1, keepdims=True)
1000 loops, best of 3: 1.5 ms per loop

In [49]: %timeit X.mean(axis=1).reshape(-1, 1)
1000 loops, best of 3: 1.52 ms per loop

In [50]: %timeit np.einsum('ij->i',X)[:,None]/X.shape[1]
1000 loops, best of 3: 832 µs per loop

2) Сравнение всего расчета -

In [52]: X = np.random.rand(500, 1000)

In [53]: %timeit X - X.mean(axis=1, keepdims=True)
100 loops, best of 3: 6.56 ms per loop

In [54]: %timeit X - X.mean(axis=1).reshape(-1, 1)
100 loops, best of 3: 6.54 ms per loop

In [55]: %timeit X - np.einsum('ij->i',X)[:,None]/X.shape[1]
100 loops, best of 3: 6.18 ms per loop

24
задан Dmitri Nesteruk 9 February 2009 в 17:05
поделиться

4 ответа

Проблема разрабатывает ориентированный на многопотоковое исполнение набор, не просто. Уверенный достаточно просто разработать набор, который может изменяться/читаться от нескольких потоков, не повреждая состояние. Но намного более трудно разработать набор, который применим, учитывая, что это обновляется от нескольких потоков. Возьмите следующий код в качестве примера.

if ( myCollection.Count > 0 ) {
  var x = myCollection[0];
}

Предполагают, что myCollection является ориентированным на многопотоковое исполнение набором, где добавляет, и обновления, как гарантируют, не повредят состояние. Этот код не ориентирован на многопотоковое исполнение и является состоянием состязания.

, Почему? Даже при том, что myCollection безопасен, нет никакой гарантии, что изменение не происходит между этими двумя вызовами метода myCollection: именовано рассчитайте и индексатор. Другой поток может войти и удалить все элементы между этими вызовами.

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

РЕДАКТИРОВАНИЕ

я развернул это обсуждение недавнего сообщения в блоге: http://blogs.msdn.com/jaredpar/archive/2009/02/11/why-are-thread-safe-collections-so-hard.aspx

31
ответ дан Eric J. 28 November 2019 в 23:28
поделиться

Добавить немного к превосходному ответу Jared: потокобезопасность не прибывает бесплатно. Многие (большинство?) наборы только используются в единственном потоке. Почему те наборы должны иметь производительность или штрафы функциональности для преодоления многопоточного случая?

6
ответ дан Jon Skeet 28 November 2019 в 23:28
поделиться

Собирая идеи из всех других ответов, я думаю, что это самый простой способ решить ваши проблемы:

Измените свой вопрос с:

«Почему не класс X вменяемый? "

-

" Как вменяемый способ сделать это с классом X? " ] в конструкторе вашего класса получите текущий диспетчер при создании ваших наблюдаемых коллекций. Поскольку, как вы указали, необходимо внести изменения в исходный поток , который может не являться основным потоком GUI. Таким образом, App.Current.Dispatcher не всегда прав, и не все классы имеют this.Dispatcher .

_dispatcher = System.Windows.Threading.Dispatcher.CurrentDispatcher;
_data = new ObservableCollection<MyDataItemClass>();
  • Используйте диспетчер для вызова разделов кода, для которых требуется оригинальный поток.

    _dispatcher.Invoke(new Action(() => { _data.Add(dataItem); }));
    
    1. Это должно помочь вам. Хотя есть ситуации, вы можете предпочесть .BeginInvoke вместо .Invoke .

    5
    ответ дан Jesse Chisholm 28 November 2019 в 23:28
    поделиться

    Если Вы хотите сойти с ума - , вот ThreadedBindingList<T>, который делает уведомления назад на потоке UI автоматически. Однако для одного потока все еще только было бы безопасно сделать обновления и т.д. за один раз.

    2
    ответ дан Marc Gravell 28 November 2019 в 23:28
    поделиться
    Другие вопросы по тегам:

    Похожие вопросы: