#include #include #include #include #include #include using std::cout; using std::endl; using std::setw; using std::flush; #include extern "C" { #include } #include "misc.h" int main( int argc, char* argv[] ) { dash::init( &argc, &argv ); dart_unit_t myid= dash::myid(); size_t numunits= dash::Team::All().size(); dash::TeamSpec<2> teamspec{}; uint32_t rowsperstrip= 0; TIFF* tif= NULL; std::chrono::time_point start, end; /* *** Part 1: open TIFF input, find out image dimensions, create distributed DASH matrix *** */ dash::Shared imagesize_shared {}; if ( 0 == myid ) { if ( 1 >= argc ) { cout << "no file given (x_x)" << endl; dash::finalize(); return EXIT_FAILURE; } tif = TIFFOpen( argv[1], "r" ); if ( NULL == tif ) { cout << "not a TIFF file (x_x)" << endl; dash::finalize(); return EXIT_FAILURE; } uint32_t bitsps= 0; uint32_t samplespp= 0; uint32_t width = 0; uint32_t height = 0; TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &width ); TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &height ); TIFFGetField(tif, TIFFTAG_BITSPERSAMPLE, &bitsps ); TIFFGetField(tif, TIFFTAG_SAMPLESPERPIXEL, &samplespp ); TIFFGetField(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip ); cout << "input file " << argv[1] << endl << " image size: " << width << " x " << height << " pixels with " << samplespp << " channels x " << bitsps << " bits per pixel, " << rowsperstrip << " rows per strip" << endl; imagesize_shared.set( {height, width} ); } imagesize_shared.barrier(); ImageSize imagesize = imagesize_shared.get(); auto distspec= dash::DistributionSpec<2>( dash::BLOCKED, dash::NONE ); dash::NArray matrix( dash::SizeSpec<2>( imagesize.height, imagesize.width), distspec, dash::Team::All(), teamspec ); /* *** part 2: load image strip by strip on unit 0, copy to distributed matrix from there, then show it *** */ matrix.barrier(); if ( 0 == myid ) { uint32_t numstrips= TIFFNumberOfStrips( tif ); tdata_t buf= _TIFFmalloc( TIFFStripSize( tif ) ); auto iter= matrix.begin(); uint32_t line= 0; start= std::chrono::system_clock::now(); for ( uint32_t strip = 0; strip < numstrips; strip++, line += rowsperstrip ) { TIFFReadEncodedStrip( tif, strip, buf, (tsize_t) -1 ); RGB* rgb= (RGB*) buf; /* it turns out that libtiff and SDL have different oponions about the RGB byte order, fix it by swaping red and blue. Do it here where the line was freshly read in. This is qicker than an extra sequential or parallel swap operation over the matrix when the lines have been out of cache already. Then again, we don't care about the colors for the rest of the code, and we can leave this out entirely. Histogram and counting objects won't produce any difference*/ std::for_each( rgb, rgb + imagesize.width * rowsperstrip, [](RGB& rgb) { std::swap( rgb.r, rgb.b ); } ); for ( uint32_t l= 0; ( l < rowsperstrip ) && (line+l < imagesize.height); l++ ) { iter = dash::copy( rgb, rgb+imagesize.width, iter ); rgb += imagesize.width; } if ( 0 == ( strip % 100 ) ) { cout << " strip " << strip << "/" << numstrips << "\r" << flush; } } end= std::chrono::system_clock::now(); cout << "read image in "<< std::chrono::duration_cast (end-start).count() << " seconds" << endl; } matrix.barrier(); if ( 0 == myid ) { show_matrix( matrix, 1200, 1000 ); } matrix.barrier(); /* *** part 3: compute historgramm in parallel *** */ { // really need 64 bits for very large images constexpr uint64_t MAXKEY = 256*3; constexpr uint64_t BINS = 17; /* Assignment: Create a distributed DASH array for the histogram of size ( 'BINS' x team size ) which is block distributed over all units. Fill it with '0' using a DASH algorithm. */ start= std::chrono::system_clock::now(); /* Assignment: Iterate over all local pixels in the distributed matrix using the local iterator. For every pixel determine the brightness bin in the histogram of 'BINS' bins. Then increment the corresponding histogram bin in the local part of the histogram by 1. */ /* Assignment: Add a barrier for the histogram data structure */ if ( 0 != myid ) { /* Assignment: For all units except unit 0, add their histogram bins to the values of the histogram of unit 0. Try using a DASH algorithm for that. */ } /* Assignment: Add a barrier for the histogram data structure */ end= std::chrono::system_clock::now(); if ( 0 == myid ) { cout << "computed parallel histogram in "<< std::chrono::duration_cast (end-start).count() << " seconds" << endl << endl; /* Assignment: Use the given function 'print_histogram' to print out the global histogram. */ } } /* from the brightness histogram we learned, that we should define all but the first two histogram bins as bright pixels */ /* Assignment: put here the limit where the pixel color is considered part of a bright object instead of the dark background. Look at the histogram you produced to find out a good limit */ const uint32_t limit= 0; dash::finalize(); return 0; }