Если вы ищете производительность, вы также можете использовать 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
Проблема разрабатывает ориентированный на многопотоковое исполнение набор, не просто. Уверенный достаточно просто разработать набор, который может изменяться/читаться от нескольких потоков, не повреждая состояние. Но намного более трудно разработать набор, который применим, учитывая, что это обновляется от нескольких потоков. Возьмите следующий код в качестве примера.
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
Добавить немного к превосходному ответу Jared: потокобезопасность не прибывает бесплатно. Многие (большинство?) наборы только используются в единственном потоке. Почему те наборы должны иметь производительность или штрафы функциональности для преодоления многопоточного случая?
Собирая идеи из всех других ответов, я думаю, что это самый простой способ решить ваши проблемы:
Измените свой вопрос с:
«Почему не класс 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); }));
Это должно помочь вам. Хотя есть ситуации, вы можете предпочесть .BeginInvoke вместо .Invoke .
Если Вы хотите сойти с ума - , вот ThreadedBindingList<T>
, который делает уведомления назад на потоке UI автоматически. Однако для одного потока все еще только было бы безопасно сделать обновления и т.д. за один раз.