Commit 98c53188 authored by Andreas Kempe's avatar Andreas Kempe

Multi-process rendering is now possible.

parent 198865b0
# Generated by YCM Generator at 2015-10-02 21:46:33.349867
# Generated by YCM Generator at 2015-10-03 19:06:59.481209
# This file is NOT licensed under the GPLv3, which is the license for the rest
# of YouCompleteMe.
......@@ -43,13 +43,15 @@ flags = [
'-DQT_NETWORK_LIB',
'-DQT_NO_DEBUG',
'-DQT_WIDGETS_LIB',
'-Dmandelbrot_EXPORTS',
'-Dmandelnet_EXPORTS',
'-I/home/andkem/Dokument/Programmering/mpi-mandelbrot',
'-I/home/andkem/Dokument/Programmering/mpi-mandelbrot/mandelbrot',
'-I/home/andkem/Dokument/Programmering/mpi-mandelbrot/network',
'-I/home/andkem/Program/imagemagick/include/ImageMagick-6',
'-I/home/andkem/Program/openmpi/include',
'-I/home/kempe/lib/include/ImageMagick-6',
'-I/tmp/tmpljiixJ',
'-I/tmp/tmpN4wYQP',
'-I/usr/include/qt5',
'-I/usr/include/qt5/QtCore',
'-I/usr/include/qt5/QtGui',
......
......@@ -10,14 +10,16 @@ find_package(Qt5Gui)
find_package(Qt5Network)
# Source files
set(SERVER_SRC server/main.cpp server/mandelbrot.cpp server/mandel_render_srv.cpp)
set(SERVER_SRC server/main.cpp server/mandel_render_srv.cpp)
set(CLIENT_SRC client/main.cpp client/main_window.cpp)
set(MANDELNET_SRC network/data_packet.cpp network/mandel_socket.cpp
network/mandel_tcp_server.cpp)
set(MANDELBROT_SRC mandelbrot/mandelbrot.cpp)
include_directories(/home/andkem/Program/imagemagick/include/ImageMagick-6
/home/kempe/lib/include/ImageMagick-6
network
mandelbrot
${Qt5Widgets_INCLUDE_DIRS}
${Qt5Gui_INCLUDE_DIRS}
${Qt5Network_INCLUD_DIRS})
......@@ -27,6 +29,7 @@ include_directories(/home/andkem/Program/imagemagick/include/ImageMagick-6
add_executable(mpi-mandel-srv ${SERVER_SRC})
add_executable(mandel-clt ${CLIENT_SRC})
add_library(mandelnet SHARED ${MANDELNET_SRC})
add_library(mandelbrot SHARED ${MANDELBROT_SRC})
find_library(Magick Magick++-6.Q16
......@@ -39,6 +42,6 @@ set(CMAKE_CXX_COMPILER mpicxx)
set(CMAKE_CXX_FLAGS "-DMAGICKCORE_HDRI_ENABLE=0 -DMAGICKCORE_QUANTUM_DEPTH=16 -std=c++11 -fPIC")
# Libraries
target_link_libraries(mpi-mandel-srv mpi ${Magick} mandelnet)
target_link_libraries(mandel-clt Qt5::Widgets Qt5::Gui ${Magick} mandelnet)
target_link_libraries(mpi-mandel-srv mpi ${Magick} mandelnet mandelbrot)
target_link_libraries(mandel-clt Qt5::Widgets Qt5::Gui ${Magick} mandelnet mandelbrot)
target_link_libraries(mandelnet Qt5::Network)
#include "main_window.h"
#include "mandelbrot.h"
#include <QPixmap>
#include <QPushButton>
#include <QDebug>
......@@ -55,8 +56,26 @@ void main_window::send_img_render()
if (!socket)
return;
QByteArray settings;
QDataStream stream(&settings, QIODevice::ReadWrite);
mandel_settings new_settings = { .re_max = 0.5,
.re_min = -1,
.im_max = 0.7,
.im_min = -0.625,
.img_width = 1064,
.img_height = 800,
.iterations = 1000};
stream << new_settings;
char* payload = new char[settings.size()];
QDataStream read_stream(&settings, QIODevice::ReadOnly);
read_stream.readRawData(payload, settings.size());
// Send an image request to the server.
data_packet rnd_packet(op_codes::RENDER_IMG, 0, nullptr);
data_packet rnd_packet(op_codes::RENDER_IMG, settings.size(), payload);
socket->send_data_packet(rnd_packet);
}
......
......@@ -87,3 +87,35 @@ double get_max_im(double im_max, double im_min, int id, int procs)
{
return im_min + ((fabs(im_max - im_min)) / procs) * (id + 1);
}
QDataStream& operator<<(QDataStream& stream, const mandel_settings& settings)
{
stream << settings.re_max;
stream << settings.re_min;
stream << settings.im_max;
stream << settings.im_min;
stream << static_cast<quint64>(settings.img_width);
stream << static_cast<quint64>(settings.img_height);
stream << static_cast<quint64>(settings.iterations);
return stream;
}
QDataStream& operator>>(QDataStream& stream, mandel_settings& settings)
{
double re_max, re_min, im_max, im_min;
quint64 img_width, img_height, iterations;
stream >> re_max >> re_min >> im_max >> im_min
>> img_width >> img_height >> iterations;
settings.re_max = re_max;
settings.re_min = re_min;
settings.im_max = im_max;
settings.im_min = im_min;
settings.img_width = img_width;
settings.img_height = img_height;
settings.iterations = iterations;
return stream;
}
#ifndef MANDELBROT_H
#define MANDELBROT_H
#include <complex>
#include <QDataStream>
struct mandel_settings
{
......@@ -15,6 +16,9 @@ struct mandel_settings
unsigned long iterations;
};
QDataStream& operator<<(QDataStream& stream, const mandel_settings& settings);
QDataStream& operator>>(QDataStream& stream, mandel_settings& settings);
class mandelbrot
{
......
......@@ -16,6 +16,7 @@ mandel_render_srv::mandel_render_srv(mandel_settings settings, std::string host,
// We only let the root process connect to the client.
if (id == 0)
{
cout << "Starting root process!" << endl;
socket = new mandel_socket(host.c_str(), port, this);
connect(socket, &mandel_socket::packet_ready, this, &mandel_render_srv::handle_recv_data);
connect(socket, &mandel_socket::disconnected, this, &mandel_render_srv::handle_network_down);
......@@ -23,7 +24,11 @@ mandel_render_srv::mandel_render_srv(mandel_settings settings, std::string host,
this, &mandel_render_srv::handle_socket_error);
}
else
{
cout << "Starting process " << id << "!" << endl;
socket = nullptr;
mpi_event_loop();
}
}
void mandel_render_srv::start_drawing()
......@@ -92,6 +97,46 @@ void mandel_render_srv::root_process_handling(unsigned long *receive_buffer)
socket->send_data_packet(packet);
}
void mandel_render_srv::mpi_event_loop()
{
double recv_buf[8];
while (true)
{
cout << "Process " << id << " in event loop!";
MPI_Status status;
// Sending the opcode as a double as well to only have to use one transmission.
MPI_Recv(&recv_buf, 8, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD, &status);
cout << "Received opcode: " << recv_buf[0] << endl;
mpi_opcodes op_code = static_cast<mpi_opcodes>(recv_buf[0]);
switch (op_code)
{
case mpi_opcodes::EXIT:
{
exit(0);
break;
}
case mpi_opcodes::RENDER:
{
mandel_settings recv_settings = { .re_max = recv_buf[1],
.re_min = recv_buf[2],
.im_max = get_max_im(recv_buf[3], recv_buf[4], id, procs),
.im_min = get_min_im(recv_buf[3], recv_buf[4], id, procs),
.img_width = static_cast<unsigned long>(recv_buf[5]),
.img_height = static_cast<unsigned long>(recv_buf[6]),
.iterations = static_cast<unsigned long>(recv_buf[7])};
settings = recv_settings;
start_drawing();
break;
}
}
}
}
void mandel_render_srv::handle_recv_data()
{
data_packet* packet = socket->get_next_packet();
......@@ -100,6 +145,35 @@ void mandel_render_srv::handle_recv_data()
{
case op_codes::RENDER_IMG:
{
QByteArray payload;
QDataStream stream(&payload, QIODevice::ReadWrite);
stream.writeRawData(packet->get_payload(), packet->get_payload_size());
mandel_settings recv_settings;
QDataStream read_stream(&payload, QIODevice::ReadOnly);
read_stream >> recv_settings;
settings = recv_settings;
double mpi_data[8];
mpi_data[0] = static_cast<double>(mpi_opcodes::RENDER);
mpi_data[1] = settings.re_max;
mpi_data[2] = settings.re_min;
mpi_data[3] = settings.im_max;
mpi_data[4] = settings.im_min;
mpi_data[5] = settings.img_width;
mpi_data[6] = settings.img_height / procs;
mpi_data[7] = settings.iterations;
// Send current render settings to other processes.
if (procs >= 2)
{
for (int i = 1; i < procs; ++i)
MPI_Send(mpi_data, 8, MPI_DOUBLE, i, 0, MPI_COMM_WORLD);
}
start_drawing();
break;
}
......
......@@ -4,6 +4,12 @@
#include "mandel_socket.h"
#include "mandelbrot.h"
enum class mpi_opcodes : int
{
EXIT = 0,
RENDER = 1
};
class mandel_render_srv : public QObject
{
public:
......@@ -14,6 +20,7 @@ class mandel_render_srv : public QObject
private:
void root_process_handling(unsigned long *receive_buffer);
void mpi_event_loop();
mandel_settings settings;
const int id;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment