Ответы с форумов MSDN

Параллельная загрузка файлов

Date: 05.09.2017 9:37:33

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

К тому же, перед измерением производительности, следует убедиться что программа корректно работает. Вы используете одну и ту же переменную (n) из нескольких потоков без всякой синхронизации, что не правильно (вы проверяли, что программа в результате скачивает?)

Message 685

Date: 05.09.2017 17:14:24

"Даже если сделать 8 отдельных методов без обращения к одной переменной (хотя обращение к переменной только в начале, разве оно влияет на производительность?), производительность падает так, что такое чуство, что операции выполняются последовательно."

Речь не о том, что это влияет на производительность, а о том, что перед измерением производительности нужно убедиться в корректности кода (да и решаемой задачи). Что вы пытаетесь выяснить? Влияние распараллеливания на скорость загрузки файлов? Для этого надо мерить суммарное время, а не время загрузки одного файла, иначе эксперимент не имеет смысла.

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

"И все же вопрос - почему не стоит рассчитывать на выгоду при распараллеливании загрузки занимающей 50 мс?"

Потому что 50 мс - слишком малое время, чтобы заметить выигрыш. Тупо погрешность измерения может перебивать результат. Распаралеливать имеет смысл что-то, что длится заметное время, нет?

Говоря о выигрыше при многопоточности, следует понимать одну вещь: параллельность полезна, если потоки не конкурируют за общие ресурсы. Бессмысленно гонять 100 потоков на двухъядерном процессоре - на переключение контекстов потеряем больше, чем на выполнение самих задач. Этот же принцип можно распространить и на сеть - если пропускная способность своего канала является лимитирующим фактором, распараллеливание не даст никакого выигрыша; если нет - может и даст. Для исследования можно попробовать вот такую программу:

	static string[] urls = new string[] {                         
            "http://example.ru/file1.zip",
            "http://example.ru/file2.zip",
            "http://example.ru/file3.zip"
        };

        static int n;
        static object sync = new object();
        static System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();

        static void Main(string[] args)
        {
            WebClient client = new WebClient();
            using (client)
            {
                //предварительно выполним длительную операцию,
                //чтобы исключить влияние инициализации CLR на последующие вычисления...
                byte[] data = client.DownloadData("http://example.com/file.png");
            }

            n = 0;
            Console.WriteLine(" *** Последовательная загрузка ***");
            sw.Start();

            //последовательно загрузим три файла...
            GetData();
            GetData();
            GetData();

            n = 0;
            Console.WriteLine();
            Console.WriteLine(" *** Параллельная загрузка ***");
            sw.Reset();
            sw.Start();
            
            //запустим три параллельных потока на загрузку тех же файлов...
            for (int i = 0; i < 3; i++)
            {
                Task t = new Task(GetData);
                t.Start();
            }
            Console.ReadKey();
        }

        static void GetData()
        {
            int count;

            lock (sync)
            {
                count = n;
                n++;
            }

            WebClient client = new WebClient();

            Console.WriteLine("Downloading " + count + ", t=" + sw.ElapsedMilliseconds.ToString() + " ms");
            byte[] data = client.DownloadData(urls[count]);
            Console.WriteLine("Downloaded " + count + ", t=" + sw.ElapsedMilliseconds.ToString() + " ms");
            
        }

Я сам сейчас не могу получить вменяемые результаты, так как у WiFi-соединения скорость слишком нестабильная. Но предварительно: при загрузке файлов около 20 КБ выигрыша не наблюдается, около мегабайта - небольшой выигрыш есть.



Автор: VadimTagil

Главная страница - Список тем - Репозиторий на GitHub