Автор Тема: многопроточность в perl  (Прочитано 3177 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Оффлайн demond

  • Заглянувший
  • Новичок
  • *
  • Сообщений: 24
  • +0/-0
  • 0
    • Просмотр профиля
    • http://
многопроточность в perl
« : 29 Ноября 2007, 22:26:38 »
проблема в следующем: скрипт получает на вход текстовый файл и кол-во потоков, далее каждый поток читаем из файла строчку (файл большой n*100000 записей, поэтому построчно) и пишет в другой (тоже один и тотже для всех потоков) файл. при этом происходит то ли затирание записей в выходном файле, то ли  во время чтения происходит считывание не всей строчки (в результате проведенных опытов, решено что проблема в чтении).
Посути происходит много поточное переписывание из одного файла в другой (для 1-го потока все работает номально)
Как можно избежать такого? предполагаю, что надо поставить блокировку на файл из которого происходит чтение, но только не понимаю как это сделать!

#!/usr/bin/perl
use strict;
use threads;
use threads::shared;

my $j = 0;
share $j;# делаем переменную общую для всех потоков
my $n=1; #для создания потоков

my $num_threads =  shift || 3; # кол-во потоков
my $path = shift || \'text.txt\';

my @threads;# будет содержать ссылки на потоки, для одновременного их запуска

# открываем файл
open(INPATH,"$path") || die "Can\'t open $path: $!";
# открываем файл для записи результатов
open(OUTPATH,"+
# создаем объекты потоки для последующего их запуска
while ($n<=$num_threads) {
  push @threads, threads->create(\\&sub_in_thread);
  $n++;
}
# одновременно запускаем все объекты потоки
foreach my $thread (@threads) {
    $thread->join();
}

close(INPATH);
close(OUTPATH);

sub sub_in_thread()
{

  do
  {
   my $str=;
   #если прочитали строку
   if($str)
   {
      chomp $str;
      print OUTPATH $str."\\n";
   }
  }while(!eof(INPATH)); #цикл будет работать пока не закончатся строки
 
}

Оффлайн ravshaniy

  • Фанат форума
  • Постоялец
  • ***
  • Сообщений: 191
  • +0/-0
  • 0
    • Просмотр профиля
    • http://
многопроточность в perl
« Ответ #1 : 30 Ноября 2007, 13:23:57 »
Многопоточное переписывание одного файла в другой ).
А конечный файл должен быть копией исходного?

Объясняю свой вопрос: без блокировки у Вас в конечном файле получится каламбур скорее всего.

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

Что вы хотите сделать?
Скопировать файл. но разбить копирование на несколько потоков? или что?

/*по некоторым причинам мне кажется будет работать так, если я не прав прошу обязательно написать мне*/
убили кенни, сволочи

Оффлайн demond

  • Заглянувший
  • Новичок
  • *
  • Сообщений: 24
  • +0/-0
  • 0
    • Просмотр профиля
    • http://
многопроточность в perl
« Ответ #2 : 30 Ноября 2007, 19:22:25 »
Задача конечно глобальнее, чем просто копирование файлов! Но любую сложную задачу имеет смысл разбить на несколько простых. Вот это одна из  простых задач!(в оригинале каждый поток кроме чтения еще производит манипуляции с прочитанной информацией).
Проблема не с записью!!! (я пробовал записывать в расшаренную переменную, а потом из нее переписывать в файл, результат тот же, кроме того каламбура не будет в выходном файле, потому что при каждой операции записи происходт сдвиг указателя в файле, и каждый поток пишит в новое место)
Проблема с чтением информации из входного файла. Весь я его прочитать в память не могу, слишком большой. А проблему я себе представляю следующим образом: при чтении из файла, если строка еще полностью не прочитана и происходит переключение контекста (управление получает другой процесс), то ни первый ни второй потоки не смогут нормально обрабатывать считанную информацию, т.к. она не полная. Как этого избежать не знаю! надо как-то не давать читать из файла, если эту операцию выполнял другой проток и не закончил ее до переключения контекста.

Оффлайн ravshaniy

  • Фанат форума
  • Постоялец
  • ***
  • Сообщений: 191
  • +0/-0
  • 0
    • Просмотр профиля
    • http://
многопроточность в perl
« Ответ #3 : 30 Ноября 2007, 23:20:43 »
Цитировать
demond:
я пробовал записывать в расшаренную переменную, а потом из нее переписывать в файл, результат тот же, кроме того каламбура не будет в выходном файле, потому что при каждой операции записи происходт сдвиг указателя в файле, и каждый поток пишит в новое место


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

Оффлайн demond

  • Заглянувший
  • Новичок
  • *
  • Сообщений: 24
  • +0/-0
  • 0
    • Просмотр профиля
    • http://
многопроточность в perl
« Ответ #4 : 30 Ноября 2007, 23:37:21 »
Цитировать
ravshaniy:
а есть гарантия того что следующий поток читающий будет соответсвовать следующиму пишущему?

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

Оффлайн ravshaniy

  • Фанат форума
  • Постоялец
  • ***
  • Сообщений: 191
  • +0/-0
  • 0
    • Просмотр профиля
    • http://
многопроточность в perl
« Ответ #5 : 01 Декабря 2007, 00:00:43 »
Цитировать
demond:
А вот как создать каждому потоку свой сектор, я что-то не представляю.


я не представляю как работает перл с памятью поэтому предлагаю чуть экономный для этого вариант

Нужно сделать следующее:
1) создаются потоки

Действия потоков.
а) открывает файл на чтение, создает свой локальный для потока указатель
б) открывает файл на запись. создает локальный для потока указатель на запись
в) устанавливает значение по умолчанию сектору
г) открывает цикл
 Действия в цикле:
 г.1) считывает строку по формуле /сектор*Количество_строк_в_секторе*количество_потоков + коунтер/

г.1.а - либо завершение цикла если со строкой не все хорошо

 г.2) записывает эту строку в указатель записи
 г.3) проверяет чтобы коунтер не превышал Количество_строк_в_секторе
  г.3.1) увеличивает коунтер
или
  г.3.2) увеличивает сектор

условие выхода из цикла eof по всей видимости

д)закрываем указатели
е)закрываем потоки ну или што там нужно сделать

2) объединение получившихся файлов если нужно

а оно по всей видимости нужно )

2.1) открывает файл на запись. создает глобальный для всех потоков указатель на запись

2.2)Создаем потоки

а) Каждый поток открывает свой файл на чтение, создает свой локальный для потока указатель
*здесь скорее всего нужно будет соблюсти тонкость и потоки должны быть в том же порядке и считать те же самые файлы*

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

в) в цикле

в.1) выбираем поток.
в.2) выполняем функцию потока в которой:
в.2.1) блокируется глобальный указатель на запись
в.2.2) октывается цикл который прочтет и впишет текущий сектор
в.2.3) передвинет соответственно курсор на чтение
в.2.4) соответственно изменит текущий сектор
в.2.4) выйдет из цикла и соответственно из функции
г)по сути все цикл сделал то что нужно
осталось только удалить не нужные файлы

это конешно без проверки. и без тестирования. и возможно сомнительно. но мне кажется где то так и можно сделать
« Последнее редактирование: 01 Декабря 2007, 00:28:06 от ravshaniy »
убили кенни, сволочи

 

Sitemap 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28