Как потоков можно избежать?

Проблема в том, что scale возвращает матрицу, которая имеет два измерения.

dat <- data.frame(col1 = 1:10)
dat$col2 <- scale(dat$col1)

lapply(dat, class)
#$col1
#[1] "integer"

#$col2
#[1] "matrix"

Обходной путь был бы таким

dat$col2 <- c(scale(dat$col1))

Теперь col2 является числовым вектором, то есть 1d атомным вектором, и dplyr::filter работает как ожидалось

dplyr::filter(dat, col1 < 4)
#  col1       col2
#1    1 -1.4863011
#2    2 -1.1560120
#3    3 -0.8257228
6
задан Jonathan Leffler 20 December 2008 в 00:01
поделиться

14 ответов

Я добавлю пример того, как функциональный код может использоваться для безопасного создания кода параллельным.

Вот некоторый код, который Вы могли бы хотеть сделать параллельно, таким образом, Вы не имеете, ожидают одного файла, чтобы закончить начинать загружать следующее:

void DownloadHTMLFiles(List<string> urls)
{
    foreach(string url in urls)
    {
         DownlaodOneFile(url);  //download html and save it to a file with a name based on the url - perhaps used for caching.
    }
}

Если у Вас есть много файлов, пользователь мог бы провести минуту или больше ожидания их всех. Мы можем переписать этот код функционально как это, и он в основном делает ту же самую вещь:

urls.ForEach(DownloadOneFile);

Обратите внимание, что это все еще работает последовательно. Однако не только это короче, мы получили важное преимущество здесь. Так как каждый вызов к функции DownloadOneFile полностью изолируется от других (в наших целях, доступная пропускная способность не является проблемой), Вы могли очень легко выгрузить функцию ForEach для другой очень похожей функции: тот, который начинает каждый вызов к DownlaodOneFile на отдельном потоке от пула потоков.

Оказывается, что .NET имеет просто такую функцию availabe использующий Параллельные Расширения. Так, при помощи функционального программирования можно изменить одну строку кода и внезапно иметь что-то выполненное параллельно, которое раньше работало последовательно. Это довольно мощно.

8
ответ дан 8 December 2019 в 02:08
поделиться

Потоков нельзя избежать, ни являются ими "трудный". Функциональное программирование является не обязательно ответом также. Платформа.NET делает поточную обработку довольно простой. С немного думал, что можно сделать разумные многопоточные программы.

Вот образец Вашего webcrawler (в VB.NET)


Imports System.Threading
Imports System.Net

Module modCrawler

    Class URLtoDest
        Public strURL As String
        Public strDest As String
        Public Sub New(ByVal _strURL As String, ByVal _strDest As String)
            strURL = _strURL
            strDest = _strDest
        End Sub
    End Class

    Class URLDownloader

        Public id As Integer
        Public url As URLtoDest

        Public Sub New(ByVal _url As URLtoDest)
            url = _url
        End Sub

        Public Sub Download()

            Using wc As New WebClient()
                wc.DownloadFile(url.strURL, url.strDest)
                Console.WriteLine("Thread Finished - " & id)
            End Using

        End Sub

    End Class

    Public Sub Download(ByVal ud As URLtoDest)
        Dim dldr As New URLDownloader(ud)
        Dim thrd As New Thread(AddressOf dldr.Download)
        dldr.id = thrd.ManagedThreadId
        thrd.SetApartmentState(ApartmentState.STA)
        thrd.IsBackground = False
        Console.WriteLine("Starting Thread - " & thrd.ManagedThreadId)
        thrd.Start()        
    End Sub

    Sub Main()

        Dim lstUD As New List(Of URLtoDest)

        lstUD.Add(New URLtoDest("http://stackoverflow.com/questions/382478/how-can-threads-be-avoided", "c:\file0.txt"))
        lstUD.Add(New URLtoDest("http://stackoverflow.com/questions/382478/how-can-threads-be-avoided", "c:\file1.txt"))
        lstUD.Add(New URLtoDest("http://stackoverflow.com/questions/382478/how-can-threads-be-avoided", "c:\file2.txt"))
        lstUD.Add(New URLtoDest("http://stackoverflow.com/questions/382478/how-can-threads-be-avoided", "c:\file3.txt"))
        lstUD.Add(New URLtoDest("http://stackoverflow.com/questions/382478/how-can-threads-be-avoided", "c:\file4.txt"))
        lstUD.Add(New URLtoDest("http://stackoverflow.com/questions/382478/how-can-threads-be-avoided", "c:\file5.txt"))
        lstUD.Add(New URLtoDest("http://stackoverflow.com/questions/382478/how-can-threads-be-avoided", "c:\file6.txt"))
        lstUD.Add(New URLtoDest("http://stackoverflow.com/questions/382478/how-can-threads-be-avoided", "c:\file7.txt"))
        lstUD.Add(New URLtoDest("http://stackoverflow.com/questions/382478/how-can-threads-be-avoided", "c:\file8.txt"))
        lstUD.Add(New URLtoDest("http://stackoverflow.com/questions/382478/how-can-threads-be-avoided", "c:\file9.txt"))

        For Each ud As URLtoDest In lstUD
            Download(ud)
        Next

        ' you will see this message in the middle of the text
        ' pressing a key before all files are done downloading aborts the threads that aren't finished
        Console.WriteLine("Press any key to exit...")
        Console.ReadKey()

    End Sub

End Module

0
ответ дан 8 December 2019 в 02:08
поделиться

Ваш определенный пример редко решается с многопоточностью. Как многие сказали, этот класс проблем является IO-bound, означая, что процессор имеет очень мало работы, чтобы сделать и тратит большую часть из, время, ожидая некоторых данных, чтобы прибыть по проводу и обработать это, и так же это должно ожидать дисковых буферов для сбрасывания так, чтобы это могло поместить больше недавно загруженных данных по диску.

Метод к производительности является через выбор () средством или эквивалентным системным вызовом. Базовый процесс должен открыть много сокетов (для загрузок поискового робота) и дескрипторы файлов (для хранения их к диску). Затем Вы устанавливаете все различные сокеты и fh к не блокирующемуся режиму, подразумевая, что вместо того, чтобы заставить Вашу программу ожидать, пока данные не доступны для чтения после издания запроса, это возвращается сразу же со специальным кодом (обычно EAGAIN), чтобы указать, что никакие данные не готовы. Если бы Вы циклично выполнились через все сокеты таким образом, то Вы опросили бы, который работает хорошо, но является все еще тратой ресурсов CPU, потому что Ваши чтения и записи будут почти всегда возвращаться с EAGAIN.

Для двигений это, все сокеты и fp's будут собраны в 'fd_set', который передается избранному системному вызову, затем программа заблокируется, ожидая на ЛЮБОМ из сокетов, и пробудит программу, когда будут некоторые данные по любому из потоков для обработки.


Другой общий падеж, вычислите связанную работу, без сомнения, лучше всего обращенного со своего рода истинным параллелизмом (как соединено к асинхронному параллелизму, представленному выше) для доступа к ресурсам нескольких CPU. В случай, что Ваша зависящая от ЦП задача работает на единственной потоковой архитектуре, определенно избегайте любого параллелизма, поскольку издержки на самом деле замедлят Вашу задачу.

0
ответ дан 8 December 2019 в 02:08
поделиться

Используйте Скрученный. "Скрученный событийно-ориентированный сетевой механизм, записанный в Python" http://twistedmatrix.com/trac/. С ним я мог сделать 100 асинхронных запросов HTTP за один раз, не используя потоки.

0
ответ дан 8 December 2019 в 02:08
поделиться

Вы могли бы посмотреть видео MSDN на языке F#: PDC 2008: введение в F#

Это включает эти две вещи, которые Вы ищете. (Функциональный + Асинхронный)

0
ответ дан 8 December 2019 в 02:08
поделиться

Для Python это похоже на интересный подход: http://members.verizon.net/olsongt/stackless/why_stackless.html#introduction

0
ответ дан 8 December 2019 в 02:08
поделиться

Там существуют некоторые хорошие библиотеки.

java.util.concurrent. ExecutorCompletionService возьмет набор фьючерсов (т.е. задачи, которые возвращают значения), обработайте их в фоновых потоках, затем закупорите их в Очереди для Вас для обработки далее, как они завершаются. Конечно, это - Java 5 и позже, так не доступно везде.

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

Точка, если можно сделать задачи независимыми, затем потокобезопасности не невозможно достигнуть с небольшой мыслью - хотя настоятельно рекомендуется оставить сложный бит (как реализация ExecutorCompletionService) эксперту...

1
ответ дан 8 December 2019 в 02:08
поделиться

Один простой способ постараться не распараллеливать в Вашем простом сценарии, должен загрузить с различных процессов. Основной процесс вызовет другие процессы с параметрами, которые загрузят файлы на локальный каталог, И затем основной процесс может сделать реальное задание.

Я не думаю, что существует любое простое решение тех проблем. Не проблема многопоточности. Это - параллелизм, которые тормозят человеческий разум.

0
ответ дан 8 December 2019 в 02:08
поделиться

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

Одна вещь, которую можно хотеть рассмотреть, порождает несколько процессов, а не несколько потоков. В случае Вы упоминаете - загружающий веб-страницы одновременно - Вы могли разделить рабочую нагрузку на несколько блоков и передать каждый блок к отдельному экземпляру инструмента (как ЗАВИХРЕНИЕ), чтобы сделать работу.

1
ответ дан 8 December 2019 в 02:08
поделиться

Параллелизм является вполне сложным предметом в информатике, которая требует хорошего понимания поведения операционной системы, а также аппаратной архитектуры.

Многопоточность имеет много реализаций на основе Ваших аппаратных средств и Вашего хостинга ОС, и столь же жесткий, как это уже, ловушки являются многочисленными. Нужно отметить, что для достижения "истинного" параллелизма, потоки являются единственным способом пойти. В основном потоки являются единственным путем к Вам как программист для совместного использования ресурсов между различными частями программного обеспечения, позволяя им работать параллельно. Параллелью необходимо полагать, что стандартный ЦП (двойной / мультиядра в стороне) может только сделать одну вещь за один раз. Понятия как контекстное переключение теперь играют роль, и у них есть свой собственный подшипник и ограничения.

Я думаю, что необходимо искать больше универсального фона на предмете, как Вы говорят перед движением о реализации параллелизма в программе.

Я предполагаю, что лучшее место для запуска является статьей Википедии о параллелизме, и продолжите оттуда.

1
ответ дан 8 December 2019 в 02:08
поделиться

Существует несколько кратких упоминаний об асинхронных моделях, но никто действительно не объяснил это так, я думал, что вмешаюсь. Наиболее распространенный метод, который я видел используемый в качестве альтернативы для многопоточности, является асинхронной архитектурой. Все, что действительно означает, - то, что вместо того, чтобы выполнить код последовательно в единственном потоке, Вы используете метод опроса, чтобы инициировать некоторые функции и затем возвращаться и проверка периодически, пока нет доступные данные.

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

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

Другой пример реального мира для системы, которая должна была выполнить много других исполняемых файлов и ожидать результатов. Это может быть сделано в потоках, но это также значительно более просто и почти так же эффективно просто исчерпать несколько внешних приложений, как Процесс возражает, затем перепроверяйте периодически, пока они все не закончены, выполнившись. Это помещает интенсивные ЦП части (под управлением код во внешних исполняемых файлах) в их собственных процессах, но обработка данных все обрабатывается асинхронно.

Lib FTP-сервера Python я продолжаю работать, pyftpdlib, использует Python asyncore библиотека для обработки служащих клиентов FTP только с единственным потоком и асинхронной связи с сокетом для передач файлов и команды/ответа.

См. дополнительные материалы для чтения страница библиотеки Python Twisted на Асинхронном программировании - в то время как несколько конкретный для Скрученного использования, это также представляет асинхронное программирование с точки зрения новичка.

4
ответ дан 8 December 2019 в 02:08
поделиться

Причина, которой функциональное программирование помогает с параллелизмом, состоит в том, не потому что это избегает использования потоков.

Вместо этого функциональное программирование проповедует неизменность и отсутствие побочных эффектов.

Это означает, что операция могла масштабироваться горизонтально к сумме N потоков или процессов, не имея необходимость волноваться о питании с общим состоянием.

22
ответ дан 8 December 2019 в 02:08
поделиться

На самом деле потоки довольно легко обработать, пока Вы не должны синхронизировать их. Обычно, Вы используете пул потоков, чтобы добавить задачу и ожидать, пока они не закончены.

Это - когда потоки должны связаться, и доступ обменялся данными структуры, что много поточная обработка становится действительно сложной. Как только у Вас есть две блокировки, можно получить мертвые блокировки, и это - то, где многопоточность становится действительно трудной. Иногда, Ваш код блокировки мог быть неверным всего несколькими инструкциями. В этом случае Вы могли только видеть ошибки в производстве на многоядерных машинах (если бы Вы разработали на одноядерном, произошел со мной), или они могли бы быть инициированы некоторыми другими аппаратными средствами или программным обеспечением. Поблочное тестирование не помогает многому здесь, тестирование находит ошибки, но Вы никогда не можете быть так же уверены как в "нормальных" приложениях.

9
ответ дан 8 December 2019 в 02:08
поделиться

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

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

1
ответ дан 8 December 2019 в 02:08
поделиться
Другие вопросы по тегам:

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