6 / 6 / 1
Регистрация: 27.08.2013
Сообщений: 128
1

Чтение/запись в файл с использованием многопоточности

06.08.2014, 01:01. Показов 15265. Ответов 38
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Доброго времени суток!
Хочу решить следующую задачу:
Есть большой бинарный файл (несколько гигабайт к примеру). Нужно разбить этот файл на части и записать в другой файл хэши этих частей, используя многопоточность (многопроцессорность). С ней я никогда не работал. Читал про процессы, потоки и т.д. Но никогда не использовал в программах.
Предполагаю сделать так
C++
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
29
30
31
32
33
34
35
36
37
38
39
#include "header.h"
using namespace std;
 
void read_file( mutex& m_arr, mutex& m_out) {
    int num;
    
        FILE *fin, *fout;
        size_t k;
        char buf[1024];
        fin = fopen("input.txt", "r");
 
        while (!feof(fin))
        {
            m_arr.lock();
            k = fread(buf, sizeof(char), 100, fin);
    
        }
        fclose(fin);
        
}
void write_file( mutex& m_arr, mutex& m_out) {
    int i = 0, num;
    
}
 
int main()
{
    
    mutex m_arr, m_out;
    thread read_thread(read_file, ref(m_arr), ref(m_out));
    thread write_thread(write_file, ref(m_arr), ref(m_out));
    if (read_thread.joinable()) read_thread.join();
    if (write_thread.joinable()) write_thread.join();
    
    return 0;
}
 
 
}
Думаю, как использовать мьютексы. Был бы признателен за подсказки, как грамотнее реализовать эту задачу. Может быть дробление, чтение файла лучше реализовывать по другому? Или многопоточность использовать по другому? Пока я предполагал, что один поток будет читать и дробить в файлы, другой хэшировать и записывать. Заранее спасибо!
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
06.08.2014, 01:01
Ответы с готовыми решениями:

Открыть текстовый файл в необходимом режиме (на чтение, на чтение и запись, на добавление)
Открыть текстовый файл в необходимом режиме (на чтение, на чтение и запись, на добавление). (В...

Чтение/запись в файл
Почему то попытка создать файл для записи или открыть какой либо файл для чтения оказывается...

Чтение и запись в файл
Здраствуйте, я в c++ оч плохо разбираюсь, помогите пожалуйсто, мне нужен скрипт который открывал бы...

Чтение и запись в файл
Задача такая: Есть файл data.txt, в нем хранятся фамилии, номера телефонов и года регистрации в...

38
327 / 230 / 55
Регистрация: 30.05.2014
Сообщений: 682
07.08.2014, 12:55 21
Author24 — интернет-сервис помощи студентам
Цитата Сообщение от Afrit Посмотреть сообщение
Я правильно полагаю, что вот в этом коде мы мапим часть файла (не равное размеру блока на количество ядер)?
Ну если я правильно понимаю, то это один блок.

Цитата Сообщение от Afrit Посмотреть сообщение
А потом мы добавляем параллельность при расчете хэша. Я правильно её реализовал, кстати?
Параллелить расчет хеша одного блока не очень просто и не понимаю зачем, ИМХО параллелить проще и лучше расчет хешей нескольких блоков. Правильно или нет - не знаю, кода в архиве не нашел.

Цитата Сообщение от Afrit Посмотреть сообщение
Меня смутила фраза про то, что у нас одновременно участвует несколько блоков. Это же не так верно?
Ну судя по коду - не так, а на мой взгляд, нужно бы.
1
6 / 6 / 1
Регистрация: 27.08.2013
Сообщений: 128
07.08.2014, 13:02  [ТС] 22
Цитата Сообщение от uglyPinokkio Посмотреть сообщение
Правильно или нет - не знаю, кода в архиве не нашел.
как так? source.rar И там тоже нет кода?
Цитата Сообщение от uglyPinokkio Посмотреть сообщение
Ну судя по коду - не так, а на мой взгляд, нужно бы.
Получается, мы должны сразу разбить проекцию на блоки? То есть взять какой-нибудь контейнер типа Pbyte. Расфасовать блоки в контейнер. и подать все эту циклу, который Вы привели?
Тогда где тут окно? Я понимаю, когда у нас один блок и окно двигается. Размер окна - размер блока. Или в окне несколько блоков? Тогда не знаю, как это реализовать...
0
327 / 230 / 55
Регистрация: 30.05.2014
Сообщений: 682
07.08.2014, 13:10 23
Цитата Сообщение от Afrit Посмотреть сообщение
Тогда где тут окно? Я понимаю, когда у нас один блок и окно двигается. Размер окна - размер блока. Или в окне несколько блоков? Тогда не знаю, как это реализовать...
Окно - отмапленная область, размер его - несколько блоков, хеши которых нужно посчитать, хеш каждого блока считается в своем потоке. Тасовать ничего никуда не надо, считаем прямо на месте.

Цитата Сообщение от Afrit Посмотреть сообщение
source.rar
А, да, сорри, вечером посмотрю, возможно начну понимать в чем проблема .

OpenMP очень удобно параллелит циклы, но только в случае, если итерации цикла независимы.
1
6 / 6 / 1
Регистрация: 27.08.2013
Сообщений: 128
07.08.2014, 15:13  [ТС] 24
Цитата Сообщение от uglyPinokkio Посмотреть сообщение
Окно - отмапленная область, размер его - несколько блоков, хеши которых нужно посчитать, хеш каждого блока считается в своем потоке. Тасовать ничего никуда не надо, считаем прямо на месте.
Перечитал Ваши посты с самого начала и понял про окно. Количество ядер, как найти я знаю. Размер окна найти труда не составит. Нужно зарезервировать пространства для окна, верно? и про контейнер я правильно сказал?
Не могли бы Вы поподробнее описать процесс от создания проекции до хэширования блоков? Буду очень признателен, если на важных участках конструкции кода приведете.

Добавлено через 1 час 44 минуты
Создаем окно
C++
1
PVOID pbmem = VirtualAlloc(NULL, dwBytesInBlock * numCPU, MEM_RELEASE | MEM_COMMIT, PAGE_READWRITE);
Указатель на начало qwFileOffset, количество файлов в блоке dwBytesInBlock. Функция хэширования блока CRC32_function.
Я не знаю, как разбить созданное окно по блокам. У меня складывается ощущение, что это надо делать параллельно, чтобы потом передать в параллельный цикл, который Вы написали. Или нет?
0
Игогошка!
1801 / 708 / 44
Регистрация: 19.08.2012
Сообщений: 1,367
07.08.2014, 19:33 25
Народ, я нифига не понял. Объясните мне, на кой все так усложнять?
Зачем тут нужны отображаемые в память файлы?
Зачем тут нужен OpenMP?
Почему бы просто-напросто не реализовать паттерн producer/consumer?
0
6 / 6 / 1
Регистрация: 27.08.2013
Сообщений: 128
07.08.2014, 20:35  [ТС] 26
Цитата Сообщение от ct0r Посмотреть сообщение
Почему бы просто-напросто не реализовать паттерн producer/consumer?
Как я понимаю, отправляем блоки. Выдаем хэш. А многопоточность? В чем плюс producer/consumer? Прочел статью на msdn, но пользы не увидел. Что упростит?
0
Игогошка!
1801 / 708 / 44
Регистрация: 19.08.2012
Сообщений: 1,367
07.08.2014, 20:41 27
Цитата Сообщение от Afrit Посмотреть сообщение
А многопоточность?
А что с ней не так? Несколько потоков есть.
Цитата Сообщение от Afrit Посмотреть сообщение
В чем плюс producer/consumer? Прочел статью на msdn, но пользы не увидел.
Считывание данных выполняется параллельно с их обработкой.
Цитата Сообщение от Afrit Посмотреть сообщение
Что упростит?
Реализацию упростит. Зачем там нужны отображаемые в память файлы и OpenMP, объясни?
0
6 / 6 / 1
Регистрация: 27.08.2013
Сообщений: 128
07.08.2014, 21:02  [ТС] 28
Цитата Сообщение от ct0r Посмотреть сообщение
Реализацию упростит. Зачем там нужны отображаемые в память файлы и OpenMP, объясни?
Я не претендую Про метод услышал от Вас, про openmp от uglyPinokkio.
Пытаюсь сделать хоть как то. Можете накидать примерный план с producer/consumer? или скинуть литературу с примерчиками?
План с кусками кода лучше всего, конечно
0
Игогошка!
1801 / 708 / 44
Регистрация: 19.08.2012
Сообщений: 1,367
07.08.2014, 23:57 29
Цитата Сообщение от Afrit Посмотреть сообщение
Можете накидать примерный план с producer/consumer?
Producer - поток, читающий файл и помещающий блоки данных в потокобезопасную очередь. Consumer - поток, берущий блоки данных из потокобезопасной очереди, считающий и записывающий хеш.
Цитата Сообщение от Afrit Посмотреть сообщение
или скинуть литературу с примерчиками?
Вбей в гугле "producer consumer" или "производитель потребитель" и выбери сам то, что поймешь лучше.
Цитата Сообщение от Afrit Посмотреть сообщение
План с кусками кода лучше всего, конечно
Код простой, должен сам осилить а вообще советую использовать для этого дела библиотеку Intel TBB - это можно сказать STL параллельного программирования.
0
327 / 230 / 55
Регистрация: 30.05.2014
Сообщений: 682
08.08.2014, 07:58 30
Лучший ответ Сообщение было отмечено Afrit как решение

Решение

Цитата Сообщение от ct0r Посмотреть сообщение
Народ, я нифига не понял. Объясните мне, на кой все так усложнять?
Это отмапить файл и посчитать в цикле хеши сложно?

Цитата Сообщение от Afrit Посмотреть сообщение
Я не знаю, как разбить созданное окно по блокам.
Примерно так:

Кликните здесь для просмотра всего текста

C++
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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
   while (qwFileSize > 0)
   {
 
      // определяем, сколько байтов надо спроецировать 
      DWORD dwBytesInBlock = sinf.dwAllocationGranularity;
      int n_blocks = omp_get_max_threads();
      DWORD dwBytesInParallelBlocks = dwBytesInBlock*n_blocks;
      std::vector<unsigned int> crc_s;
      crc_s.resize(n_blocks,0);
      if (qwFileSize < dwBytesInParallelBlocks)
      {
         n_blocks = 1;
         if (qwFileSize < dwBytesInBlock)
         {
            dwBytesInBlock = (DWORD)qwFileSize;
         }
         dwBytesInParallelBlocks = dwBytesInBlock;
      }
 
      PBYTE pbFile = (PBYTE)MapViewOfFile(hFileMapping, FILE_MAP_READ, (DWORD)(qwFileOffset >> 32), // начальный байт 
         (DWORD) (qwFileOffset & 0xFFFFFFFF), // в файле
         dwBytesInParallelBlocks); // число проецируемых байтов
 
      #pragma omp parallel for
      for(int n_block=0;n_block<n_blocks;n_block++)
      {
         crc_s[n_block] = CRC32_function(pbFile+dwBytesInBlock*n_block, dwBytesInBlock);
      }
 
      for(int n_block=0;n_block<n_blocks;n_block++)
      {
         cout<<"n_block "<<n_block<<" crc "<<crc_s[n_block]<<endl;
      }
 
      // прекращаем проецирование представления, чтобы в адресном пространстве 
      // не образовалось несколько представлений одного файла
 
      UnmapViewOfFile(pbFile);
 
      // переходим к следующей группе байтов в файле 
      qwFileOffset += dwBytesInParallelBlocks;
      qwFileSize -= dwBytesInParallelBlocks;
 
   }
1
Игогошка!
1801 / 708 / 44
Регистрация: 19.08.2012
Сообщений: 1,367
08.08.2014, 08:41 31
Цитата Сообщение от uglyPinokkio Посмотреть сообщение
Это отмапить файл и посчитать в цикле хеши сложно?
Я не говорю, что это сложно. Я говорю, что это ненужное усложнение в коде, которое данной задаче не требуется.
0
327 / 230 / 55
Регистрация: 30.05.2014
Сообщений: 682
08.08.2014, 08:42 32
Цитата Сообщение от ct0r Посмотреть сообщение
Я говорю, что это ненужное усложнение в коде, которое данной задаче не требуется.
Ну вон в 40 строк усложненное решение, простое должно быть видимо короче?

UP.

И оно само параллелится по количеству ядер в среде исполнения, отметим на всякий случай.
0
6 / 6 / 1
Регистрация: 27.08.2013
Сообщений: 128
08.08.2014, 11:09  [ТС] 33
Цитата Сообщение от uglyPinokkio Посмотреть сообщение
Примерно так:
Здорово! Спасибо!
Есть еще пару глупых вопросов.
1) Почему так нельзя?
C++
1
2
3
char path[MAX_PATH] = { 0 };
scanf("%s", path);
    HANDLE hFile = CreateFile(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
Сначала ругается на несоответствие форматов LPWSTR с char. Если дописать LPWSTR, тоже ничего хорошего не получается.

2) А можно в данной программе применить smart pointers? Я читал про них, но в основном говорится про то, что удобно подчищаться память за объектами, созданными с new. В деструкторе. Тут ничего с new не создается.
0
327 / 230 / 55
Регистрация: 30.05.2014
Сообщений: 682
08.08.2014, 11:50 34
Цитата Сообщение от Afrit Посмотреть сообщение
Здорово! Спасибо!
Да не за что. С такой функцией нет большого смысла параллелить расчет, узким местом будет чтение с диска.
Попробуй распараллелить вычисление хеша вместе с отображением файла.

Цитата Сообщение от Afrit Посмотреть сообщение
Сначала ругается на несоответствие форматов LPWSTR с char.
Ну видимо определен дефайн UNICODE.
LPWSTR - это указатель на строку, в которой каждый символ занимает два байта.

Цитата Сообщение от Afrit Посмотреть сообщение
2) А можно в данной программе применить smart pointers?
А зачем?
0
6 / 6 / 1
Регистрация: 27.08.2013
Сообщений: 128
08.08.2014, 12:21  [ТС] 35
Цитата Сообщение от uglyPinokkio Посмотреть сообщение
Попробуй распараллелить вычисление хеша вместе с отображением файла.
Про вычисление хэша понятно. Попробую. А вместе с отображением файла - то, что уже сделано? дробление окна на блоки? или нет?

Цитата Сообщение от uglyPinokkio Посмотреть сообщение
А зачем?
А тут в задании это есть, как дополнение (многопоточность тоже там была). Этим часто пользуются? И как это можно применить, если можно?
0
327 / 230 / 55
Регистрация: 30.05.2014
Сообщений: 682
08.08.2014, 13:13 36
Цитата Сообщение от Afrit Посмотреть сообщение
А вместе с отображением файла - то, что уже сделано? дробление окна на блоки?
Нет. Можно попробовать сделать несколько окон размером в один блок в разных потоках.

Цитата Сообщение от Afrit Посмотреть сообщение
А тут в задании это есть
smart pointers - понятие широкое, используется для автоматизации управления памятью, куда их применить в этой задаче - я без понятия.
0
6 / 6 / 1
Регистрация: 27.08.2013
Сообщений: 128
08.08.2014, 13:43  [ТС] 37
uglyPinokkio, ясно. Тогда smart pointers пока оставлю.
А если я хочу запустить программу из командой строки, указывая путь и размер блока, нужно сделать path и dwBytesInBlock глобальными?
Потом
C++
1
int main(path, dwBytesInBlock)
. Верно? или как то по другому?
И еще, например, размер блока сделать необязательной переменной для ввода. Если пользователь не ввел размер, то программа сама задаст ей размер. Как это можно реализовать?
Я почитал про функции с переменным количеством переменных и везде только int Func (int a,...). То есть произвольное количество переменных int на входе. А тут точно знаем 1 или 2 переменные, но разного формата
0
327 / 230 / 55
Регистрация: 30.05.2014
Сообщений: 682
08.08.2014, 14:10 38
Цитата Сообщение от Afrit Посмотреть сообщение
int main(path, dwBytesInBlock)
с main так не получится.

http://lord-n.narod.ru/downloa... 6/0604.htm

Глобальным ничего делать не надо, В main разбираешь параметры, если что-то не задано, присваиваешь значение по умолчанию и передаешь в свою функцию.
0
6 / 6 / 1
Регистрация: 27.08.2013
Сообщений: 128
08.08.2014, 18:12  [ТС] 39
uglyPinokkio, Только радовался, что все работает. А тут обнаружил совсем непонятную проблему.
Если ввести количество байт не равное мегабайту. То программа вылетает....

Необработанное исключение по адресу 0x00BE56E3 в Map5.exe: 0xC0000005: нарушение прав доступа при чтении по адресу 0x0004CCCB
Из-за чего это?
Проект прикрепляю.
Вложения
Тип файла: rar Map5.rar (7.71 Мб, 13 просмотров)
0
08.08.2014, 18:12
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
08.08.2014, 18:12
Помогаю со студенческими работами здесь

Чтение и запись в файл
Текст находится в файле, имя которого вводится с клавиатуры. Вывод результата также осуществляется...

Запись и чтение в файл
Вариант 1 Написать программу, которая считывает из текстового файла три предложения и выводит их в...

Чтение запись в файл
Доброго времени суток. Мир нестаит на месте как и я ) недавно доделаную благодаря форумчанам...

Чтение и запись в файл
#include &lt;iostream&gt; #include &lt;fstream&gt; using namespace std; int main() { int S, x, i, z, k,f;...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
39
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru