0 / 0 / 0
Регистрация: 29.08.2015
Сообщений: 4
1

Написать консольную программу для генерации сигнатуры указанного файла (задействовать параллелизм)

20.09.2016, 22:47. Показов 3003. Ответов 5
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Здравствуйте, дорогие форумчане.

На днях подкинули заданице:

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

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

Мне ввиду специфики работы, с потоками, параллелизмом и boost'ом общаться не приходилось.
Может кто подсказать, в какую сторону вообще смотреть?
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
20.09.2016, 22:47
Ответы с готовыми решениями:

Нужно написать консольную программу для нахождения значения F в заданном промежутке с шагом 0,5
Здравствуйте, уважаемые программисты! Прошу у Вас помощи, помогите пожалуйста! Нужно написать...

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

Написать консольную программу
Народ помогите плз :) Напишите консольную программу которая считывает с консоли целое число ,...

Написать программу для распечатки на экране монитора указанного в варианте набора символ
Написать программу использую цикл for с использованием оператора для распечатки на экране монитора...

5
1375 / 519 / 72
Регистрация: 21.07.2015
Сообщений: 1,304
21.09.2016, 16:49 2
Цитата Сообщение от Kap98k Посмотреть сообщение
Может кто подсказать, в какую сторону вообще смотреть?
В сети мало примеров работы с потоками или с объектами синхронизации?
0
0 / 0 / 0
Регистрация: 29.08.2015
Сообщений: 4
28.09.2016, 10:59  [ТС] 3
Цитата Сообщение от shmkv Посмотреть сообщение
В сети мало примеров работы с потоками или с объектами синхронизации?
Тут не поспоришь, но когда не сталкивался вообще с этим, то трудно решить с чем работать WinApi, boost или еще чем
Пока решил пользоваться thread из STL, чтобы абстрагироваться от платформы (а может это иллюзия ).

Возник вопрос следующего характера.
Создается отдельный поток на чтение из файла, потоку передаем функцию (код ниже).
Поток отсоединяется и работает в фоне. С маленькими файлами проблем нет (в пределах 10 - 20 Мб).
А вот при чтении файла в 110 Мб регулярно вылетает ios:failure.

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
void SignCreater::readFile(){
    try{
        if(!hInnerFile){
            //здесь что то должно быть
        }
        else
        {
            while(!hInnerFile.good()){
                //blockSize  вводится пользователем.
                shared_ptr<char> pInBlock(new char [blockSize], [](char * buf) {delete[] buf;});
                hInnerFile.read(pInBlock.get(), blockSize); 
                //две очереди для передачи данных другим потокам
                fifoWrite.push(pInBlock);
                fifoHash.push(pInBlock);
            }
            //atomic для синхронизации
            finish.store(true);
            hInnerFile.close();
 
        }
    }
    catch(system_error &err){
 
    }
}
Подскажите, где я дурак?
0
1375 / 519 / 72
Регистрация: 21.07.2015
Сообщений: 1,304
28.09.2016, 14:57 4
Цитата Сообщение от Kap98k Посмотреть сообщение
то трудно решить с чем работать WinApi, boost или еще чем
Работа с потоками и с синхронизацией поддерживается всеми современными С++11(14) компиляторами "из коробки". Используй шатный std::thread. WinApi - это непереносимо и имеет смыл использовать лишь если нужна супер оптимизация под винду.

Добавлено через 16 минут
Цитата Сообщение от Kap98k Посмотреть сообщение
Подскажите, где я дурак?
А если просто без потоков эту функцию запускаешь, то работает? Просто тут ты отрывок дал и не видно как из других потоков ты с этим хозяйством взаимодействуешь.
1
0 / 0 / 0
Регистрация: 29.08.2015
Сообщений: 4
28.09.2016, 18:59  [ТС] 5
Цитата Сообщение от shmkv Посмотреть сообщение
абота с потоками и с синхронизацией поддерживается всеми современными С++11(14) компиляторами "из коробки". Используй шатный std::thread. WinApi - это непереносимо и имеет смыл использовать лишь если нужна супер оптимизация под винду.
Вот там, где я сейчас работаю с современными компиляторами беда. А тут за это задание взялся и понял, что работал больше с Си, чем С++ и STL.

Цитата Сообщение от shmkv Посмотреть сообщение
если просто без потоков эту функцию запускаешь, то работает? Просто тут ты отрывок дал и не видно как из других потоков ты с этим хозяйством взаимодействуешь.
Сама функция работает криво, неважно в потоке или нет. Вроде нашел место:

C++
1
shared_ptr<char> pInBlock(new char [blockSize], [ ](char * buf) {delete [ ] buf;});
потому что, если заменить этот "умный" указатель на

C++
1
char * pInBlock = new char [blocksize];
то работает адекватно и нормально видит конец файла, не уходя в бесконечный цикл (хотя вроде умный указатель инициализирую как надо).


Кликните здесь для просмотра всего текста
Очередь
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
45
46
47
48
49
50
#include <queue>
#include <memory>
#include <mutex>
#include <condition_variable>
 
template <class T>
class tsQueue
{
private:
    mutable std::mutex trafLight;
    std::queue<T> fifo;
    std::condition_variable tCondition;
 
public:
    tsQueue(){}
    tsQueue(tsQueue const& another){
        std::lock_guard<std::mutex> lk(another.trafLight);
        fifo = another.fifo;
    }
 
    tsQueue& operator= (const tsQueue&) = delete;
 
    void push (T new_value){
        std::lock_guard<std::mutex> lk(trafLight);
        fifo.push(new_value);
        tCondition.notify_one();
    }
 
    void pop (T& value){
        std::unique_lock<std::mutex> lk(trafLight);
        tCondition.wait(lk, [this]{return !fifo.empty();});
        value = fifo.front();
        fifo.pop();
    }
 
    T pop (){
        std::unique_lock<std::mutex> lk(trafLight);
        tCondition.wait(lk, [this]{return !fifo.empty();});
        T value = fifo.front();
        fifo.pop();
        return value;
    }
 
    bool empty()const {
        std::lock_guard<std::mutex> lk(trafLight);
        return fifo.empty();
    }
 
 
};

Кликните здесь для просмотра всего текста
Основной класс
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
45
46
47
48
49
50
51
52
53
54
#ifndef SIGN_H
#define SIGN_H
 
#include <iostream>
#include <fstream>
#include <exception>
#include <stdexcept>
#include <thread>
#include <atomic>
 
#include "safequeu.h"
 
#define MAXLEN 128
#define DEFBLOCKSIZE 1024 // размер блока в Кб
 
using namespace std;
 
class SignCreater {
private:
    char innerFile [MAXLEN];
    char outerFile [MAXLEN];
    unsigned int blockSize;
    std::atomic<bool> finish;
    ifstream hInnerFile;
    ofstream hOuterFile;
    tsQueue<std::shared_ptr<char>> fifoWrite;
    tsQueue<std::shared_ptr<char>> fifoHash;
    tsQueue<unsigned int> fifoAnswerHash;
 
public:
    SignCreater(){
        finish.store(false);
        blockSize = DEFBLOCKSIZE * 1024;
        for (int i =0 ;i < MAXLEN; i++)
            innerFile[i]=0, outerFile[i]=0;
 
    }
    ~SignCreater(){
        if(hInnerFile.is_open())
            hInnerFile.close();
        if(hOuterFile.is_open())
            hOuterFile.close();
    }
 
    void processing();
    void getInOutFile();
    void readFile();
    void writeFile();
    uint32_t CRC32(unsigned char *block, unsigned int len);
 
};
 
 
#endif // SIGN_H

Кликните здесь для просмотра всего текста
Методы класса
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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#include "signClass.h"
#include <future>
 
void SignCreater::getInOutFile(){
    char ch = 0;
 
    do {
        try {
            cout<<"Введите полный путь до входящего файла:"<<endl;
            cin.unsetf(ios::skipws);
            cin.getline(innerFile, MAXLEN);
            if(cin.good()){
                hInnerFile.exceptions(ios::failbit|ios::badbit|ios::eofbit);
                hInnerFile.open(innerFile, ios::out|ios::binary);
 
                cout<<"Enter path for outputfile: "<<endl;
                cin.getline(outerFile, MAXLEN);
                if(outerFile == 0){
                    cout<<"File will be create in local directory!"<<endl;
 
                }
                hOuterFile.exceptions(ios::failbit|ios::badbit);
                hOuterFile.open(outerFile, ios::in|ios::binary|ios::app);
 
                cout<< "Enter size of block (Kb): ";
                cin>>blockSize;
                if(cin.good())
                {
                    if(blockSize == 0){
                       blockSize = DEFBLOCKSIZE;
                    }
                    blockSize *= 1024;
                }
                break;
            }
 
        }
        catch (ios::failure &err){
            cerr<<"Ошибка: "<<err.what()<<endl;
            cerr<<"Невозможно найти или открыть Inner файл!"<<endl;
            cin.clear();
            cout<<"Хотите попробовать еще раз? y/n"<<endl;
            cin>>ch;
        }
        catch (range_error &err){
            cerr<<"Ошибка: "<< err.what()<<endl;
            cin.clear();
            cout<<"Хотите попробовать еще раз? y/n"<<endl;
            cin>>ch;
        }
    } while(ch == 'y');
}
 
void SignCreater::readFile(){
    unsigned int size;
 
    hInnerFile.seekg(0, ios::end);
    size = hInnerFile.tellg();
    hInnerFile.seekg(0, ios::beg);
 
    try{
        if(!hInnerFile.is_open()){
 //           throw system_error(errno);
        }
        else
        {
            int k=0;
            while(!hInnerFile.fail()&& !hInnerFile.eof()){
                if(size<blockSize)
                    blockSize = size;
                shared_ptr<char> pInBlock(new char [blockSize], [](char * buf) {delete[] buf;});
                hInnerFile.read(pInBlock.get(), blockSize);
                fifoWrite.push(pInBlock);
                fifoHash.push(pInBlock);
               size -= blockSize;
               ++k;
               cout<<k<<endl;
            }
            finish.store(true);
            hInnerFile.close();
 
        }
    }
    catch(system_error &err){
 
    }
}
 
//Функция перед запуском должна проверяться на наличие элементов в очереди
//Должна быть функция обрабатывающая очередь и передающая указатель блока на запись и подсчет хэша
 
void SignCreater::writeFile(){
    try{
        if(!hOuterFile){
            //здесь что то должно быть
        }
        else{
            hOuterFile.clear();
            while(!finish.load() && !fifoWrite.empty()){
                shared_ptr<char> pOutBlock(new char [2048], [] (char *buf){delete [] buf;});
                fifoWrite.pop(pOutBlock);
                hOuterFile.write(reinterpret_cast<char*>(pOutBlock.get()), 2048);
            }
            cout<<"Finish:"<<finish<<endl;
        }
    }
    catch (system_error &err){
 
    }
 
}
 
 
void SignCreater::processing(){
    this->getInOutFile();
 
    try {
        std::thread readingThread(&SignCreater::readFile, this);
            if(readingThread.joinable())
                readingThread.detach();
 
        std::thread writeThread(&SignCreater::writeFile, this);
            if(writeThread.joinable())
                writeThread.join();
 
    }
    catch(system_error& err){
        cerr<<"Error thread: "<<err.what()<<endl;
    }
}
0
0 / 0 / 0
Регистрация: 29.08.2015
Сообщений: 4
30.09.2016, 22:44  [ТС] 6
Итоговый рабочий вариант в приложении, может кому и пригодится.

shmkv спасибо за внимание к вопросу )
Вложения
Тип файла: zip Signature.zip (10.7 Кб, 112 просмотров)
0
30.09.2016, 22:44
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
30.09.2016, 22:44
Помогаю со студенческими работами здесь

Написать программу для проверки указанного ниже свойства последовательности, вводимой с клавиатуры
Число вводимых элементов последовательности заранее неизвестно и определяется пользователем. Если...

Написать программу, переводящую сумму в рублях в евро для указанного обменного курса
Написать программу, переводящую сумму в рублях в евро для указанного обменного курса. Ответ вывести...

Консольную программу написать в графическом интерфейсе
Прошу Вашей помощи, так как не работал c++ builder. Программу написал консольную, но сказали...

Написать программу оператора цикла for для распечатки на экране монитора указанного в варианте набора символов
A B C D E E A C D E E D A D E E D C A E E D C B A


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

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

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