Модераторы: Partizan, gambit
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Создание множества потоков 
:(
    Опции темы
Lex101
Дата 7.3.2011, 22:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 10
Регистрация: 31.12.2010

Репутация: нет
Всего: нет



Добрый вечер! Есть задача - многопоточные векторные вычисления. Есть 3 массива, в первых двух рандомные значения, а в третьем - результат их перемножения. Размерность массивов - ну скажем 100млн элементов. И всё это дело нужно разбивать на огромное количество поток, причём количество произвольное - от 500 до 600 допустим.

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

Код

using System;
using System.Threading;

namespace ConsoleApplication1
{
    class Program
    {
        //создаём массив потоков
        static public Thread[] trArr;
        //создаём массивы для вычислений
        static public sbyte[] Arr1;
        static public sbyte[] Arr2;
        static public sbyte[] Arr3;
        //создаём массив, в котором будет храниться диапазон вычислений
        static public int[] ArrInt;

        static void Main(string[] args)
        {
            //инициализируем массивы
            Random r1 = new Random();
            Random r2 = new Random();
            Arr1 = new sbyte[100000000];
            Arr2 = new sbyte[100000000];
            Arr3 = new sbyte[100000000];
            ArrInt = new int[2];
            trArr = new Thread[512];
            for (int i = 0; i < 100000000 - 1; i++)
            {
                Arr1[i] = (sbyte)r1.Next(1, 10);
                Arr2[i] = (sbyte)r2.Next(1, 10);
                
            }
            ArrInt[0] = 0;
            ArrInt[1] = 100000000 - 1;

            Console.WriteLine("Память выделена, нажмите Enter");
            Console.ReadLine();
            //создаём множество потоков, которые будут выполнять метод Count и передаём в него диапазон вычислений из ArrInt
            for (int i = 0; i < 512; i++)
            {
                if (i == 511)
                {
                    trArr[i] = new Thread(new ParameterizedThreadStart(Count));
                    ArrInt[0] = (i + 1) * 195312;
                    ArrInt[1] = 100000000;
                    trArr[i].Start(ArrInt);
                }
                else
                {
                    trArr[i] = new Thread(new ParameterizedThreadStart(Count));
                    ArrInt[0] = 195312 * i;
                    ArrInt[1] = ((i + 1) * 195312) - 1;
                    trArr[i].Start(ArrInt);
                }
            }
            //ждём завершения всех потоков
            for (int i = 0; i < 512; i++)
            {
                trArr[i].Join();
            }
            //выводим некоторые значения из результирующего массива
            Console.WriteLine("Готово");
            Console.WriteLine(Arr3[0]);
            Console.WriteLine(Arr3[50]);
            Console.WriteLine(Arr3[49424]);
            Console.WriteLine(Arr3[99463148]);
            Console.ReadLine();
        }

        //метод умножения элементов первых двух массивов.
        static void Count(object o)
        {
            int[] bArr = (int[])o;
            for (int i = bArr[0]; i < bArr[1] - 1; i++)
            {
                Arr3[i] = (sbyte)(Arr1[i] * Arr2[i]);
            }
           
        }
    }
}

PM MAIL   Вверх
Экскалупатор
Дата 8.3.2011, 00:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1746
Регистрация: 1.4.2009
Где: г. Минск

Репутация: 11
Всего: 24



Цитата(Lex101 @  7.3.2011,  21:12 Найти цитируемый пост)
Размерность массивов - ну скажем 100млн элементов.

хотел бы я посмотреть как ты будешь все это обрабатывать.

Цитата(Lex101 @  7.3.2011,  21:12 Найти цитируемый пост)
И всё это дело нужно разбивать на огромное количество поток, причём количество произвольное - от 500 до 600 допустим.

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

Добавлено @ 00:45
Цитата(Lex101 @  7.3.2011,  21:12 Найти цитируемый пост)
for (int i = 0; i < 100000000 - 1; i++)

тут ты делаешь не 100 000 000 итераций а 99 999 999, а значений в массиве все же 100 000 000, последнее не создается

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

Это сообщение отредактировал(а) Экскалупатор - 8.3.2011, 00:46
PM MAIL ICQ   Вверх
Lex101
Дата 8.3.2011, 00:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 10
Регистрация: 31.12.2010

Репутация: нет
Всего: нет



1) А что такого в такой большой размерности?
памяти сожрёт не мало, и всего-то.
2) Про практическое применение я не говорил, а сказал, что есть такая задача!
3) ну ошибся на чуток, не обработается один элемент, не страшно

Поток помечен как остановленный Stopped - а не как спящий.

Надеюсь бесполезных замечаний больше не будет, очень надеюсь на помощь в решении этой задачи!
PM MAIL   Вверх
Экскалупатор
Дата 8.3.2011, 01:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1746
Регистрация: 1.4.2009
Где: г. Минск

Репутация: 11
Всего: 24



Lex101, ну ладно, не буду делать "бесполезных замечаний". 
по существу.
я думаю все потому что у тебя в методе идет работа с одними и теми же данными, и потоки не могут их между собой поделить, потому что метод статический(т.е. один на все приложение) и данные тоже.
для примера, если сделать метод Count не статическим, и убрать из него использование статических переменных, то он начинает выполняться оооооочень долго.
для примера вот так:
Код

 public void Count(object o)
        {
            for (int i = 0; i < 1000; ++i)
            {
                Console.WriteLine(i);
            }
            Console.WriteLine(Thread.CurrentThread.Name + " end");
        }


при этом он долго и нудно(у меня минут 5) выводит числа в консоль не останавливаясь, потом пишет что поток завершился.
это было по существу, надеюсь помог. остальное это архитектура.

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

или нужно реализовать потокобезопасный способ доступа к данным.

но это опять же личные наблюдения

Это сообщение отредактировал(а) Экскалупатор - 8.3.2011, 01:43
PM MAIL ICQ   Вверх
Lex101
Дата 8.3.2011, 02:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 10
Регистрация: 31.12.2010

Репутация: нет
Всего: нет



Благодарю за советы!
считает долго только из-за того, что выводит на консоль. 
А делать метод нестатическим - значит фигачить его в класс. Думаю стоит попробовать раскидать логику по классам.
PM MAIL   Вверх
Экскалупатор
Дата 8.3.2011, 02:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1746
Регистрация: 1.4.2009
Где: г. Минск

Репутация: 11
Всего: 24



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


Цитата(Lex101 @  8.3.2011,  01:17 Найти цитируемый пост)
считает долго только из-за того, что выводит на консоль. 

оно же ничего не считает, просто работа распределяется "более-менее равномерно" между всеми создаваемыми потоками, по этому до окончания одно из потоков проходит долго времени, потому что они по сути не выполняются параллельно, у меня стоит двухядерный процессор, можно предположить что одновременно могут выполняться два потока, но вывод на консоль показывает что это не так, все же один поток всегда приоритетнее...
PM MAIL ICQ   Вверх
Lex101
Дата 8.3.2011, 12:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 10
Регистрация: 31.12.2010

Репутация: нет
Всего: нет



Колоссальное замедление при выводе в консоль связано только с отрисовкой самих элементов в консоли. 
PM MAIL   Вверх
-Mikle-
Дата 8.3.2011, 14:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Невидимка Vingrad'а
***


Профиль
Группа: Экс. модератор
Сообщений: 1672
Регистрация: 22.6.2003
Где: Казахстан, Астана

Репутация: 17
Всего: 59



По своему опыту подтверждаю на все 100. Любые операции вывода (даже в консоль) всегда очень медленные.


--------------------
Если тебе плюют в спину, значит ты впереди...
PM   Вверх
Экскалупатор
Дата 8.3.2011, 14:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1746
Регистрация: 1.4.2009
Где: г. Минск

Репутация: 11
Всего: 24



да тут не в том вопрос что медленно, я просто сказал что потоки не прекращают свою работу, и выводят информацию от начала и до конца. то что медленно это детали. просто у человека была проблема что потоки умирали, я показал что так они не умирают.

а консоль не при чем
PM MAIL ICQ   Вверх
-Mikle-
Дата 9.3.2011, 18:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Невидимка Vingrad'а
***


Профиль
Группа: Экс. модератор
Сообщений: 1672
Регистрация: 22.6.2003
Где: Казахстан, Астана

Репутация: 17
Всего: 59



а, точно smile отошли от темы че-то...


--------------------
Если тебе плюют в спину, значит ты впереди...
PM   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Прежде чем создать тему, посмотрите сюда:
mr.DUDA
THandle

Используйте теги [code=csharp][/code] для подсветки кода. Используйтe чекбокс "транслит" если у Вас нет русских шрифтов.
Что делать если Вам помогли, но отблагодарить помощника плюсом в репутацию Вы не можете(не хватает сообщений)? Пишите сюда, или отправляйте репорт. Поставим :)
Так же не забывайте отмечать свой вопрос решенным, если он таковым является :)


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, mr.DUDA, THandle.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Общие вопросы по .NET и C# | Следующая тема »


 




[ Время генерации скрипта: 0.0803 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.