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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> многопоточность 
:(
    Опции темы
Ronin08
Дата 28.3.2008, 22:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


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

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



Доброго времени суток!
я уже поднимал эту тему, но ответа не получил.
повторюсь
нучжно перемножить матрицу на вектор, но чтобы каждое новое значение в результирующем векторе (для тех кто забыл мат-ку матрица*вектор=вектор) высчитывалось в отдельно потоке.
Буду очень благодарен за пример
--------------------
Зачем вставать рано или поздно? Надо вставать вовремя
PM MAIL   Вверх
marcusmae
Дата 28.3.2008, 22:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


stravaganza
**


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

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



Ronin08, вот та самая тема. Скажите, пожалуйста, точно : на какой вопрос Вы не получили ответ? Требуется ли решить вместо Вас поставленную задачу?

Пример



Это сообщение отредактировал(а) marcusmae - 28.3.2008, 22:29


--------------------
ἀπὸ μηχανῆς θεός
PM MAIL ICQ GTalk   Вверх
Ronin08
Дата 28.3.2008, 22:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


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

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



ни в коем случае
просто я не могу въехать как передать одной функции другую
понимаю что с помощью делегатов
но видимо что-то не улавливаю
вот как я делаю
Код

class Program
    {
        static void Main(string[] args)
        {
            string m;
            int n;
            m = Console.ReadLine();
            n = Convert.ToInt16(m);

            int[,] Arr1 = new int[n, n];
            ArrayTwo.CreateTwoDimAr(Arr1);
            ArrayTwo.PrintArr("array1", Arr1);

            int[,] Arr2 = new int[n, n];
            ArrayTwo.CreateTwoDimAr(Arr2);
            ArrayTwo.PrintArr("array2", Arr2);

            int[,] Arr3 = new int[n, n];
            ArrayTwo.MultyMatrix(Arr1, Arr2, Arr3);
            ArrayTwo.PrintArr("array3", Arr3);

            for (int pot = 0; pot < 4; pot++)
            {
                Thread t = new Thread((new ThreadStart(PotokDelegate)););  //в этом месте явно проблема!!!
                t.Start();
            }
        }

        internal delegate void PotokDelegate(int i, int j, int[,] A);

        class ArrayTwo
        {
            private static Random rnd = new Random();
            

            public static void CreateTwoDimAr(int[,] A)
            {
                for (int i = 0; i < A.GetLength(0); i++)
                {
                    for (int j = 0; j < A.GetLength(1); j++)
                    {
                        A[i, j] = rnd.Next(1, 100);
                    }
                }
            }

            public static void PrintArr(string name, int[,] A)
            {
                Console.WriteLine(name);
                for (int i = 0; i < A.GetLength(0); i++)
                {
                    for (int j = 0; j < A.GetLength(1); j++)
                    {
                        Console.Write("\t" + " {0} ", A[i, j]);
                    }
                    Console.WriteLine();
                }
            }

            public static void MultyMatrix(int[,] A, int[,] B, int[,] C)
            {
                if (A.GetLength(1) != B.GetLength(0))
                    Console.WriteLine("MultMatr: ошибка размерности!");
                else
                {
                    for (int i = 0; i < A.GetLength(0); i++)
                    {
                        for (int j = 0; j < A.GetLength(1); j++)
                        {
                        
                            Potok ( i, j, A, B, C); 
                        }
                        
                    }
                }


            }

            public static void Potok(int i, int j, int[,] A, int[,] B, int[,] C)
            {
                int res = 0;
                for (int k = 0; k < A.GetLength(1); k++)
                    res += A[i, k] * B[k, j];
                C[i, j] = res;


            }
        }
    }


Это сообщение отредактировал(а) Ronin08 - 28.3.2008, 22:54
--------------------
Зачем вставать рано или поздно? Надо вставать вовремя
PM MAIL   Вверх
marcusmae
Дата 28.3.2008, 22:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


stravaganza
**


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

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



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

Код

                // The main idea of this statment is to "link" thread with the
                // proc it have to run.
                Thread t = new Thread(new ParameterizedThreadStart(
                    Program.ArrayTwo.Potok));


Функция Potok по аргументам не подходит, поэтому я создаю ещё одну, которая будет служить "подложкой" для вызова :

Код

            public static void Potok(object obj)
            {
                object[] threadProcArgs = (object[])obj;
                ArrayTwo.Potok((int)threadProcArgs[0], (int)threadProcArgs[1],
                    (int[,])threadProcArgs[2], (int[,])threadProcArgs[3],
                    (int[,])threadProcArgs[4]);
            }


- просто доверительно преобразуем аргументы из неизвестно чего в пару индексов и тройку матриц.
Далее, раз процедура потока у нас имеет аргументы, то при старте потока мы могли бы их инициализировать. Следующий код закомментирован, подставьте в него актуальные параметры :

Код

                // TODO :
                // For the following assignments the actual values of i, j, A, B, C
                // should be provided.

                // args[0] = i; args[1] = j;
                // args[2] = A; args[3] = B; args[4] = C;


Наконец, стартуем поток с данными аргументами :

Код

                // Here you are starting to run on thread t the associated proc.
                t.Start((object)threadProcArgs);


Итого, получается следующая заготовка :

Код

    class Program
    {
        static void Main(string[] args)
        {
            string m;
            int n;
            m = Console.ReadLine();
            n = Convert.ToInt16(m);

            int[,] Arr1 = new int[n, n];
            ArrayTwo.CreateTwoDimAr(Arr1);
            ArrayTwo.PrintArr("array1", Arr1);

            int[,] Arr2 = new int[n, n];
            ArrayTwo.CreateTwoDimAr(Arr2);
            ArrayTwo.PrintArr("array2", Arr2);

            int[,] Arr3 = new int[n, n];
            ArrayTwo.MultiplyMatrix(Arr1, Arr2, Arr3);
            ArrayTwo.PrintArr("array3", Arr3);

            for (int pot = 0; pot < 4; pot++)
            {
                // The main idea of this statment is to "link" thread with the
                // proc it have to run.
                Thread t = new Thread(new ParameterizedThreadStart(
                    Program.ArrayTwo.Potok));

                // Create an objects array for the parameters list.
                object[] threadProcArgs = new object[5];

                // TODO :
                // For the following assignments the actual values of i, j, A, B, C
                // should be provided.

                // args[0] = i; args[1] = j;
                // args[2] = A; args[3] = B; args[4] = C;

                // Here you are starting to run on thread t the associated proc.
                t.Start((object)threadProcArgs);
            }
        }

        class ArrayTwo
        {
            private static Random rnd = new Random();

            public static void CreateTwoDimAr(int[,] A)
            {
                for (int i = 0; i < A.GetLength(0); i++)
                {
                    for (int j = 0; j < A.GetLength(1); j++)
                    {
                        A[i, j] = rnd.Next(1, 100);
                    }
                }
            }

            public static void PrintArr(string name, int[,] A)
            {
                Console.WriteLine(name);
                for (int i = 0; i < A.GetLength(0); i++)
                {
                    for (int j = 0; j < A.GetLength(1); j++)
                    {
                        Console.Write("\t" + " {0} ", A[i, j]);
                    }
                    Console.WriteLine();
                }
            }

            public static void MultiplyMatrix(int[,] A, int[,] B, int[,] C)
            {
                if (A.GetLength(1) != B.GetLength(0))
                    Console.WriteLine("MultMatr: ошибка размерности!");
                else
                {
                    for (int i = 0; i < A.GetLength(0); i++)
                    {
                        for (int j = 0; j < A.GetLength(1); j++)
                        {

                            Potok(i, j, A, B, C);
                        }

                    }
                }


            }

            public static void Potok(object obj)
            {
                object[] threadProcArgs = (object[])obj;
                ArrayTwo.Potok((int)threadProcArgs[0], (int)threadProcArgs[1],
                    (int[,])threadProcArgs[2], (int[,])threadProcArgs[3],
                    (int[,])threadProcArgs[4]);
            }

            static void Potok(int i, int j, int[,] A, int[,] B, int[,] C)
            {
                int res = 0;
                for (int k = 0; k < A.GetLength(1); k++)
                    res += A[i, k] * B[k, j];
                C[i, j] = res;


            }
        }
    }
}


Продолжайте, если будут вопросы - всегда пожалуйста! smile 


--------------------
ἀπὸ μηχανῆς θεός
PM MAIL ICQ GTalk   Вверх
Ronin08
Дата 28.3.2008, 23:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


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

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



Цитата

Функция Potok по аргументам не подходит, поэтому я создаю ещё одну, которая будет служить "подложкой" для вызова :
  
Код

public static void Potok(object obj)
            {
                object[] threadProcArgs = (object[])obj;
                ArrayTwo.Potok((int)threadProcArgs[0], (int)threadProcArgs[1],
                    (int[,])threadProcArgs[2], (int[,])threadProcArgs[3],
                    (int[,])threadProcArgs[4]);
            }

а как быть в случае, когда мы не знаем при компиляции сколько потоков будет
пользователь сам должен вводить
я сделал цикл с 4 потоками для примера 



Это сообщение отредактировал(а) Ronin08 - 28.3.2008, 23:14
--------------------
Зачем вставать рано или поздно? Надо вставать вовремя
PM MAIL   Вверх
Dennnis
Дата 28.3.2008, 23:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Правильно, там где ты указал есть проблема, но не толко там. Делегат - это указатель на функцию. Это значит что ему необходимо задать функцию, которую он будет вызывать при выполнении. Причем ThreadStart и есть делегат вида delegate void ThreadStart(). Он тебе не подходит, нужен ParameterizedThreadStart.
Вот примерно как надо (сам не проверял smile ):
Код

using System.Threading;
class Program
    {
        static void Main(string[] args)
        {
            string m;
            int n;
            m = Console.ReadLine();
            n = Convert.ToInt16(m);
            int[,] Arr1 = new int[n, n];
            ArrayTwo.CreateTwoDimAr(Arr1);
            ArrayTwo.PrintArr("array1", Arr1);
            int[,] Arr2 = new int[n, n];
            ArrayTwo.CreateTwoDimAr(Arr2);
            ArrayTwo.PrintArr("array2", Arr2);
            int[,] Arr3 = new int[n, n];
            ArrayTwo.MultyMatrix(Arr1, Arr2, Arr3);
            Thread.CurrentThread.Sleep(1000); //Ждем когда все посчитается
            ArrayTwo.PrintArr("array3", Arr3);
        }

        class ArrayTwo
        {
            private static Random rnd = new Random();
            
            public static void CreateTwoDimAr(int[,] A)
            {
                for (int i = 0; i < A.GetLength(0); i++)
                {
                    for (int j = 0; j < A.GetLength(1); j++)
                    {
                        A[i, j] = rnd.Next(1, 100);
                    }
                }
            }
            public static void PrintArr(string name, int[,] A)
            {
                Console.WriteLine(name);
                for (int i = 0; i < A.GetLength(0); i++)
                {
                    for (int j = 0; j < A.GetLength(1); j++)
                    {
                        Console.Write("\t" + " {0} ", A[i, j]);
                    }
                    Console.WriteLine();
                }
            }

            public static void MultyMatrix(int[,] A, int[,] B, int[,] C)
            {
                if (A.GetLength(1) != B.GetLength(0))
                    Console.WriteLine("MultMatr: ошибка размерности!");
                return;

                for (int i = 0; i < A.GetLength(0); i++)
                {
                    for (int j = 0; j < A.GetLength(1); j++)
                    {
                        Thread thread = new Thread(new ParameterizedThreadStart(Potok));
                        thread.Start(new object[]{ i, j, A, B, C });
                    }
                }
                
            }

            object locker = new object();
            public static void Potok(object obj)
            {
                object[] arr = (object[])obj;
                int i = (int)arr[0];
                int j = (int)arr[0];
                int[,] A = (int[,])arr[0];
                int[,] B = (int[,])arr[0];
                int[,] C = (int[,])arr[0];
                int res = 0;
                for (int k = 0; k < A.GetLength(1); k++)
                    res += A[i, k] * B[k, j];

                lock(locker)/*на всякий случай:)*/{
                    C[i, j] = res;}
            }
        }
    }


--------------------
Get Rich or Die Tryin'
PM   Вверх
marcusmae
Дата 28.3.2008, 23:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


stravaganza
**


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

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



Цитата(Ronin08 @  28.3.2008,  23:14 Найти цитируемый пост)
а как быть в случае, когда мы не знаем при компиляции сколько потоков будет


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

Цитата(Dennnis @  28.3.2008,  23:23 Найти цитируемый пост)
Делегат - это указатель на функцию.


Лучше не надо так говорить. Если те, кто так говорят не понимают различий, то это ещё не значит, что их нет. Делегат - это делегат. Указатель на функцию - это указатель на функцию.

Цитата(Dennnis @  28.3.2008,  23:23 Найти цитируемый пост)
Это значит что ему необходимо задать функцию, которую он будет вызывать при выполнении.


Если Он - это делегат, то нет, не значит. Функцию будет вызывать поток, а делегат здесь является способом указания метода в качестве аргумента конструктора класса Thread.

Цитата(Dennnis @  28.3.2008,  23:23 Найти цитируемый пост)
Вот примерно как надо (сам не проверял  ):

А в чём моя ошибка и что изменилось?

Код

                        thread.Start(new object[]{ i, j, A, B, C });


- так можно

Метод Potok c явным указанием типов зря убрали - пусть бы другой, c object, его вызывал, зато аккуратно. Хотя, дело вкуса.

А, или эта реплика - не мне? smile 

Это сообщение отредактировал(а) marcusmae - 28.3.2008, 23:52


--------------------
ἀπὸ μηχανῆς θεός
PM MAIL ICQ GTalk   Вверх
Ronin08
Дата 28.3.2008, 23:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


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

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



Dennnis, в этом случае проблемка с 
 
Код

public static void Potok(object obj)
            {
                object[] arr = (object[])obj;
                int i = (int)arr[0];
                int j = (int)arr[0];
                int[,] A = (int[,])arr[0];
                int[,] B = (int[,])arr[0];
                int[,] C = (int[,])arr[0];
                int res = 0;
                for (int k = 0; k < A.GetLength(1); k++)
                    res += A[i, k] * B[k, j];

                lock(locker)/*на всякий случай:)*/{
                    C[i, j] = res;}
            }

Ошибка:Unable to cast object of type 'System.Int32' to type 'System.Int32[,]'.
у нас ведь двумерный массив

Добавлено через 4 минуты
marcusmae , в месте 

Код

{
                object[] threadProcArgs = (object[])obj;
                ArrayTwo.Potok((int)threadProcArgs[0], (int)threadProcArgs[1],
                    (int[,])threadProcArgs[2], (int[,])threadProcArgs[3],
                    (int[,])threadProcArgs[4]);
}

Ошибка: Object reference not set to an instance of an object.
--------------------
Зачем вставать рано или поздно? Надо вставать вовремя
PM MAIL   Вверх
marcusmae
Дата 29.3.2008, 00:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


stravaganza
**


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

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



Цитата(Ronin08 @  28.3.2008,  23:59 Найти цитируемый пост)
Ошибка: Object reference not set to an instance of an object.


Аргументы указали там где было закомментировано? Какие?

Цитата(Ronin08 @  28.3.2008,  23:59 Найти цитируемый пост)
Ошибка:Unable to cast object of type 'System.Int32' to type 'System.Int32[,]'.


Копипаст :

Код

                int i = (int)arr[0];
                int j = (int)arr[1];
                int[,] A = (int[,])arr[2];
                int[,] B = (int[,])arr[3];
                int[,] C = (int[,])arr[4];




--------------------
ἀπὸ μηχανῆς θεός
PM MAIL ICQ GTalk   Вверх
Ronin08
Дата 30.3.2008, 00:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


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

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



Цитата

Аргументы указали там где было закомментировано? Какие?

вот такие:
Код

 for (int pot = 0; pot < 4; pot++)
            {
                Thread t = new Thread(new ParameterizedThreadStart(
                Program.ArrayTwo.Potok));                           
                object[] threadProcArgs = new object[5];
                object[] arr = (object[])threadProcArgs;
                int i, j;
                int[,] A;
                int[,] B;
                int[,] C;
                arr[0] = i; arr[1] = j;
                arr[2] = A; arr[3] = B; arr[4] = C; // или что-то в этом роде!
                  
               
 t.Start((object)threadProcArgs);
            }


Это сообщение отредактировал(а) Ronin08 - 30.3.2008, 01:17
--------------------
Зачем вставать рано или поздно? Надо вставать вовремя
PM MAIL   Вверх
marcusmae
Дата 30.3.2008, 02:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


stravaganza
**


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

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



Ronin08, странно это видеть при том, что Вы вроде бы располагаете готовым кодом, понимаете алгоритм и представляете, каким образом его разделять на потоки. В t.Start Вам нужно передать аргументы - те самые аргументы, с которыми будет работать вложенный цикл в процедуре Potok. У Вас они называются Arr1, Arr2, Arr3, i - это индекс строки, j - индекс столбца. Оба индекса Вы фиксируете. Следовательно, цикл, вероятно, должен содержать что-то вроде :

Код

                    for (int i = 0; i < Arr1.GetLength(0); i++)
                    {
                        for (int j = 0; j < Arr2.GetLength(1); j++)
                        {

                            ...

                            t.Start((object)threadProcArgs);
                        }
                   }


В этом случае потоков будет создано в количестве m * n. Вы, кажется, хотите делать меньше?.. Тогда нужно сделать ещё один цикл внутри функции Potok, который будет перебирать индексы i,j в диапазоне, отведённом каждому потоку (передавать границы диапазонов в качестве параметров).

Я понятно излагаю?..


--------------------
ἀπὸ μηχανῆς θεός
PM MAIL ICQ GTalk   Вверх
Dennnis
Дата 30.3.2008, 11:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Цитата(marcusmae @  28.3.2008,  23:27 Найти цитируемый пост)
А, или эта реплика - не мне? smile 

Точно smile 

Цитата(marcusmae @  28.3.2008,  23:27 Найти цитируемый пост)
Лучше не надо так говорить. Если те, кто так говорят не понимают различий, то это ещё не значит, что их нет. Делегат - это делегат. Указатель на функцию - это указатель на функцию.


Wikipedia:
Цитата

Делегат (англ. delegates) — типобезопасный указатель на функцию. Делегаты введены в C# и других языках технологии Microsoft .NET реализованной в виде платформы .NET Framework для определения прототипа функции обратного вызова.



Цитата(Ronin08 @  28.3.2008,  23:59 Найти цитируемый пост)
Ошибка:Unable to cast object of type 'System.Int32' to type 'System.Int32[,]'.

Моя ошибка, вобщем вот как надо:
Код

using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;

namespace ConsoleApplication1
{
    
    class Program
    {
        static void Main(string[] args)
        {
            string m;
            int n;
            m = Console.ReadLine();
            n = Convert.ToInt16(m);

            int[,] Arr1 = new int[n, n];
            ArrayTwo.CreateTwoDimAr(Arr1);
            ArrayTwo.PrintArr("array1", Arr1);

            int[,] Arr2 = new int[n, n];
            ArrayTwo.CreateTwoDimAr(Arr2);
            ArrayTwo.PrintArr("array2", Arr2);

            int[,] Arr3 = new int[n, n];
            ArrayTwo.MultyMatrix(Arr1, Arr2, Arr3);
            Thread.Sleep(1000); //Ждем когда посчитается
            ArrayTwo.PrintArr("array3", Arr3);
        }


        class ArrayTwo
        {
            private static Random rnd = new Random();

            public static void CreateTwoDimAr(int[,] A)
            {
                for (int i = 0; i < A.GetLength(0); i++)
                {
                    for (int j = 0; j < A.GetLength(1); j++)
                    {
                        A[i, j] = rnd.Next(1, 100);
                    }
                }
            }
            public static void PrintArr(string name, int[,] A)
            {
                Console.WriteLine(name);
                for (int i = 0; i < A.GetLength(0); i++)
                {
                    for (int j = 0; j < A.GetLength(1); j++)
                    {
                        Console.Write("\t" + " {0} ", A[i, j]);
                    }
                    Console.WriteLine();
                }
            }

            public static int threadCount = 1; //Количество потоков

            public static void MultyMatrix(int[,] A, int[,] B, int[,] C)
            {
                if (A.GetLength(1) != B.GetLength(0))
                {
                    Console.WriteLine("MultMatr: ошибка размерности!");
                    return;
                }

                int len = A.GetLength(0);

                int range = len / threadCount; // кол-во векторов на кажный поток

                Thread thread;

                int begin = 0;
                int end = 0;
                for (int i = 0; i < threadCount - 1; i++)
                {
                    end = begin + range;
                    thread = new Thread(new ParameterizedThreadStart(Potok));
                    thread.Start(new object[] { begin, end, A, B, C });
                }
                //Для последнего потока
                thread = new Thread(new ParameterizedThreadStart(Potok));
                thread.Start(new object[] { end, len, A, B, C });
            }

            public static void Potok(object obj)
            {
                object[] arr = (object[])obj;
                int begin = (int)arr[0];
                int end = (int)arr[1];
                int[,] A = (int[,])arr[2];
                int[,] B = (int[,])arr[3];
                int[,] C = (int[,])arr[4];
                int len = A.GetLength(1);

                for (int i = begin; i < end; i++)
                {
                    for (int j = 0; j < len; j++)
                    {

                        int res = 0;
                        for (int k = 0; k < len; k++)
                        {
                            res += A[i, k] * B[k, j];
                        }
                        C[i, j] = res;

                    }
                }

            }
        }
    }
}


Это сообщение отредактировал(а) Dennnis - 30.3.2008, 11:28
--------------------
Get Rich or Die Tryin'
PM   Вверх
Ronin08
Дата 31.3.2008, 19:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


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

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



marcusmae  и Dennnis  спасибо за ответы, 
но вот возникла новая проблема.
В нашем коде, потоки запускаются в цикле поочереди, но надо сделать так чтобы они запускались одновременно. Как это можно организовать?

--------------------
Зачем вставать рано или поздно? Надо вставать вовремя
PM MAIL   Вверх
mr.DUDA
Дата 31.3.2008, 19:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


3D-маньяк
****


Профиль
Группа: Экс. модератор
Сообщений: 8244
Регистрация: 27.7.2003
Где: город-герой Минск

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



Модератор: Пожалуйста, один топик - один вопрос.


--------------------
user posted image
PM MAIL WWW   Вверх
Ronin08
Дата 31.3.2008, 19:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


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

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



так это ведь все одна и та же тема
"Перемножение матриц при вычислениии эллементов матрицы в разных потоках, с одновременным запуском потоков"  smile 


--------------------
Зачем вставать рано или поздно? Надо вставать вовремя
PM MAIL   Вверх
Dennnis
Дата 31.3.2008, 20:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Запускаются они по очереди но работают одновременно.
Запуск потока занимает доли % от продолжительности его работы.
Запустить несколько потоков одновременно можно только в том случае если они запускаются разными потоками созданными до этого.
--------------------
Get Rich or Die Tryin'
PM   Вверх
Ronin08
Дата 31.3.2008, 20:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


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

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



Если я не ошибаюсь, то в последнем варианте кода 
Код

public static void MultyMatrix(int[,] A, int[,] B, int[,] C)
            {
                string  potstr;
                int potnum;
                Console.Write("Vvedite chislo potokov -> ");
                potstr = Console.ReadLine();
                potnum = Convert.ToInt16(potstr);
                int threadCount = potnum; //Количество потоков

                int time1, time2, timeres;
                time1= System.Environment.TickCount;

                if (A.GetLength(1) != B.GetLength(0))
                {
                    Console.WriteLine("MultMatr: ошибка размерности!");
                    return;
                }

                int len = A.GetLength(0);

                int range = len / threadCount; // кол-во векторов на кажный поток

                Thread thread;

                int begin = 0;
                int end = 0;
                for (int i = 0; i < threadCount - 1; i++)
                {
                    end = begin + range;
                    thread = new Thread(new ParameterizedThreadStart(Potok));
                    thread.Start(new object[] { begin, end, A, B, C });
                    
                }
                //Для последнего потока
                thread = new Thread(new ParameterizedThreadStart(Potok));
                thread.Start(new object[] { end, len, A, B, C });
                time2= System.Environment.TickCount;
                timeres = time1 - time2;
                Console.WriteLine(" Vremia vipolnenia {0}", timeres);
            }

            public static void Potok(object obj)
            {
                object[] arr = (object[])obj;
                int begin = (int)arr[0];
                int end = (int)arr[1];
                int[,] A = (int[,])arr[2];
                int[,] B = (int[,])arr[3];
                int[,] C = (int[,])arr[4];
                int len = A.GetLength(1);

                for (int i = begin; i < end; i++)
                {
                    for (int j = 0; j < len; j++)
                    {

                        int res = 0;
                        for (int k = 0; k < len; k++)
                        {
                            res += A[i, k] * B[k, j];
                        }
                        C[i, j] = res;

                    }
                }

            }

дело обстоит так: поток1 создался->просчитался эл-т матрици (или эллементы) -> поток1 запустился
потом следующий поток2 создался->просчитался эл-т матрици (или эллементы) -> поток2 запустился

а надо поток1 создался-> просчитался эл-т матрици (или эллементы)
потом следующий поток2 создался->просчитался эл-т матрици (или эллементы)
а уже потом
поток1 зпустился (Start)
поток1 зпустился (Start)
т.е. типа "Все потоки, айда запускайтесь"



Это сообщение отредактировал(а) Ronin08 - 31.3.2008, 20:44
--------------------
Зачем вставать рано или поздно? Надо вставать вовремя
PM MAIL   Вверх
marcusmae
Дата 31.3.2008, 21:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


stravaganza
**


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

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



Цитата(Ronin08 @  31.3.2008,  20:24 Найти цитируемый пост)
Если я не ошибаюсь, то в последнем варианте кода


Ronin08, если я правильно понял, то Вы ошибаетесь. Содержимое Potok начинает выполняться в момент вызова метода Start для соответствующего потока. Можете считать, что потоки начинают работать почти одновременно, поскольку никакие два события не могут физически одновременно произойти на последовательной аппаратуре.

Разъясню ещё один момент : после вызова Start для одного из потоков, в основном потоке происходит немедленный (асинхронный) возврат. То есть, основной поток не ожидает, пока вспомогательный получит какой-либо результат в методе Potok, а спокойно себе идёт дальше по программе, то есть, последовательно вызывает метод Start для всех потоков. 

Это сообщение отредактировал(а) marcusmae - 31.3.2008, 21:31


--------------------
ἀπὸ μηχανῆς θεός
PM MAIL ICQ GTalk   Вверх
Ronin08
Дата 31.3.2008, 21:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


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

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



marcusmae, все это понятно, что одновременно не может быть, что все процессы выполняются квазипараллельно и т.д.
Но давайте представим ситуацию, что нам надо перемножить матрицы 500*500 и при этом все вычисления надо разбить на 300 потоков, где гарантия, что все потоки будут задействованы!
--------------------
Зачем вставать рано или поздно? Надо вставать вовремя
PM MAIL   Вверх
marcusmae
Дата 31.3.2008, 22:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


stravaganza
**


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

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



Цитата(Ronin08 @  31.3.2008,  21:48 Найти цитируемый пост)
где гарантия, что все потоки будут задействованы


Все ли будут задействованы - зависит от алгоритма. В текущем варианте, на сколько я могу видеть, некратный остаток от деления нагрузки на потоки вообще не учитывается. Кроме того, имеется ошибка, связанная с тем, что в цикле маркеры начала и конца - begin и end - не модифицируются. Рекомендую для начала прогнать многопоточный алгоритм, как он есть, в одном потоке (вместо t.Start вызывать Potok c соотв. аргументами). Ранее чем будут получены правильные результаты, говорить наверно не о чем, да?..


--------------------
ἀπὸ μηχανῆς θεός
PM MAIL ICQ GTalk   Вверх
Dennnis
Дата 31.3.2008, 23:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Цитата(marcusmae @  31.3.2008,  22:52 Найти цитируемый пост)
В текущем варианте, на сколько я могу видеть, некратный остаток от деления нагрузки на потоки вообще не учитывается.

Остаток от деления нагрузки на потоки выполняется последним созданным потоком.

Цитата(marcusmae @  31.3.2008,  22:52 Найти цитируемый пост)
Рекомендую для начала прогнать многопоточный алгоритм, как он есть, в одном потоке (вместо t.Start вызывать Potok c соотв. аргументами).

Прогонял - всё сходится (RND заменял на i + j smile )
--------------------
Get Rich or Die Tryin'
PM   Вверх
marcusmae
Дата 1.4.2008, 00:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


stravaganza
**


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

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



Цитата(Dennnis @  31.3.2008,  23:42 Найти цитируемый пост)
RND заменял на i + j


А зачем?

Уж не знаю, как проверяли... Вот здесь :

Код

                int begin = 0;
                int end = 0;
                for (int i = 0; i < threadCount - 1; i++)
                {
                    end = begin + range;


разве правильно, что end меняется единственный раз в таком цикле (не говоря уж о begin)? Или я чего-то недопонимаю?

Добавлено через 1 минуту и 53 секунды
Цитата(Dennnis @  31.3.2008,  23:42 Найти цитируемый пост)
Остаток от деления нагрузки на потоки выполняется последним созданным потоком.


Понял, вижу.


--------------------
ἀπὸ μηχανῆς θεός
PM MAIL ICQ GTalk   Вверх
Dennnis
Дата 1.4.2008, 05:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Цитата(marcusmae @  1.4.2008,  00:25 Найти цитируемый пост)
разве правильно, что end меняется единственный раз в таком цикле (не говоря уж о begin)? Или я чего-то недопонимаю?

Нет не правильно.
Вот как правильно:
Код

                int begin = 0;
                int end = 0;
                for (int i = 0; i < threadCount - 1; i++)
                {
                    end = begin + range;
                    thread = new Thread(new ParameterizedThreadStart(Potok));
                    thread.Start(new object[] { begin, end, A, B, C });
                    begin = end;
                }

Проверил с исправлениями, все нормально.
Исходник по которому считал в пр. файле.

Присоединённый файл ( Кол-во скачиваний: 5 )
Присоединённый файл  Program.cs 7,28 Kb
--------------------
Get Rich or Die Tryin'
PM   Вверх
Ronin08
Дата 1.4.2008, 20:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


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

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



на сколько я знаю в С++ есть такое свойство suspend;
Например, xxx = create Thread(...,suspend);
это говорит о том, что после создания потоков, они "подвешиваются"
а потом можно просто в цикле запускать star;
О такой одновременности я говорил, так как на сомо создание потоков тратится много ресурсов;
 

Это сообщение отредактировал(а) Ronin08 - 1.4.2008, 20:34
--------------------
Зачем вставать рано или поздно? Надо вставать вовремя
PM MAIL   Вверх
marcusmae
Дата 1.4.2008, 22:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


stravaganza
**


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

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



Цитата(Ronin08 @  1.4.2008,  20:34 Найти цитируемый пост)
на сколько я знаю в С++ есть такое свойство suspend


C++ - это язык, и у него нет свойств. Вероятно, речь о каком-то пакете, поддерживающем многопоточность? = Например, WINAPI или POSIX pThreads или boost::thread. Во всех трёх возможность Suspend присутствует в том или ином виде. Присутствует и в .NET - Thread.Suspend metod. 

Следующий тезис неверен :

Цитата(Ronin08 @  1.4.2008,  20:34 Найти цитируемый пост)
на сомо создание потоков тратится много ресурсов


При "создании" потока (new Thread(...)) ничего особенного не происходит, вся вычислительная сложность находится в методе Potok, который запустится только после вызова thread.Start(...).

Боюсь, сейчас Вы у себя делаете какие-то неверные выводы. Может, стоит увеличить теоретические познания?..


--------------------
ἀπὸ μηχανῆς θεός
PM MAIL ICQ GTalk   Вверх
Ronin08
Дата 1.4.2008, 22:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


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

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



Цитата

C++ - это язык, и у него нет свойств

Можно было догадаться, что я описался smile 
я имел в виду у метода create Thread()
--------------------
Зачем вставать рано или поздно? Надо вставать вовремя
PM MAIL   Вверх
marcusmae
Дата 1.4.2008, 23:03 (ссылка) |  (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


stravaganza
**


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

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



Цитата(Ronin08 @  1.4.2008,  22:23 Найти цитируемый пост)
я имел в виду у метода create Thread()


да, есть такой : CreateThread function. Ну можно, кстати, если скучно, и его поприменять в C#.


--------------------
ἀπὸ μηχανῆς θεός
PM MAIL ICQ GTalk   Вверх
Страницы: (2) [Все] 1 2 
Ответ в темуСоздание новой темы Создание опроса
Прежде чем создать тему, посмотрите сюда:
mr.DUDA
THandle

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


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

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


 




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


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

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