Difference between revisions of "DPS915/M-N-M"

From CDOT Wiki
Jump to: navigation, search
(Final version's errors, warnings and observations)
 
(30 intermediate revisions by 3 users not shown)
Line 147: Line 147:
 
</pre>
 
</pre>
  
=== Assignment 1 ===
 
 
==== Muhammad Ahsan: Prime Number Generator( 1,000,000,000 primes) ====
 
==== Muhammad Ahsan: Prime Number Generator( 1,000,000,000 primes) ====
  
Line 161: Line 160:
  
 
</pre>
 
</pre>
=== Assignment 1 ===
 
==== Nitin Prakash Panicker: LZW File Compression ====
 
  
 
<pre>
 
<pre>
 +
/** {{{ http://code.activestate.com/recipes/576559/ (r2) */
 +
/*
 +
Copyright (c) 2008 Florian Mayer
  
Flat profile:
+
  Permission is hereby granted, free of charge, to any person obtaining a copy
 
+
  of this software and associated documentation files (the "Software"), to deal
 
+
  in the Software without restriction, including without limitation the rights
 
+
  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
Each sample counts as 0.01 seconds.
+
copies of the Software, and to permit persons to whom the Software is
 
+
furnished to do so, subject to the following conditions:
  %  cumulative  self              self    total         
 
 
 
  time  seconds  seconds    calls  ns/call  ns/call  name   
 
 
 
  99.46    48.19    48.19                            CLZWCompressFile::Compress(char*, char*)
 
 
 
  0.33    48.35    0.16 17122488    9.34    9.34 CLZWCompressFile::getc_src()
 
 
 
  0.21    48.45    0.10 7095561    14.09    14.09  CLZWCompressFile::putc_comp(int)
 
 
 
</pre>
 
 
 
=== Source Code for LZW File Compression===
 
 
 
 
 
 
 
[[Media:LZW.zip]]
 
 
 
=== lzw.h ===
 
 
 
<pre>
 
 
 
#ifndef UPRIGHT_LZW_H
 
 
 
#define UPRIGHT_LZW_H
 
 
 
 
 
  
 +
The above copyright notice and this permission notice shall be included in
 +
all copies or substantial portions of the Software.
  
 +
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 +
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 +
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 +
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 +
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 +
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 +
THE SOFTWARE.
 +
*/
  
/* LZW.h by N.A.Bozinis @ 19/01/2010 08:55:52
+
#include <iostream>
 
+
#include <vector>
* ----------------------------------------------------------------------------------
 
 
 
*
 
 
 
* Plain C++ port of LZW compression algorithm and code originally (c) Mark R. Nelson
 
 
 
* http://marknelson.us/1989/10/01/lzw-data-compression
 
 
 
* Variable bit length encoding idea and code originally by Michael Dipperstein
 
 
 
* http://michael.dipperstein.com/lzw
 
 
 
*
 
 
 
* There are a lot of compression classes floating around but most are based on the
 
 
 
* zlib (zip/unzip) library, which is good but a bit of overkill for simple and small
 
 
 
* code. LZW combines decent compression ratios with very small code footprint. If
 
 
 
* you need something more powerful here are a few resources:
 
 
 
*
 
 
 
*      http://www.codeproject.com/KB/files/zip_utils.aspx
 
 
 
*      http://www.codeproject.com/KB/cpp/xzipunzip.aspx
 
 
 
*      http://www.codeproject.com/KB/cpp/ChauMemzip.aspx
 
 
 
*
 
 
 
* Microsoft types can check the CAB protocol that is available in all windows:
 
 
 
*      http://www.codeproject.com/KB/files/CABCompressExtract.aspx
 
 
 
*      http://msdn.microsoft.com/en-us/library/bb417343.aspx
 
 
 
*
 
 
 
*/
 
 
 
 
 
 
 
#include <stdio.h>
 
 
 
#include <stdlib.h>
 
 
 
#include <limits.h>
 
 
 
 
#include <string.h>
 
#include <string.h>
  
#include <assert.h>
+
using namespace std;
 
 
#define ATLASSERT assert
 
 
 
 
 
 
 
/* NOTE: function and variable names left as much as possible matching the original
 
 
 
LZW.c by Mark, naturally bundled in classes to get rid of static/globals etc
 
 
 
*/
 
 
 
 
 
 
 
#define MIN_CODE_LEN    9                  /* min # bits in a code word */
 
 
 
#define MAX_CODE_LEN    20                  /* max # bits in a code word */
 
 
 
#define CURRENT_MAX_CODES(x)    (1UL << (x))
 
 
 
 
 
 
 
#define FIRST_CODE      (1 << CHAR_BIT)    /* value of 1st string code */
 
 
 
 
 
 
 
#if (MIN_CODE_LEN <= CHAR_BIT)
 
 
 
#error Code words must be larger than 1 character
 
 
 
#endif
 
 
 
 
 
 
 
#if (MAX_CODE_LEN >= 25)
 
 
 
#error Code words must fit in an integer
 
 
 
#endif
 
 
 
 
 
 
 
 
 
 
 
/* VARIABLE BIT LENGTH ENCODING
 
 
 
* Instead of using a fixed number of bits for code words, we start at 9 (=MIN_CODE_LEN)
 
 
 
* and go up to BITS (<=MAX_CODE_LEN) so that small files are tightly packed and larger
 
 
 
* files are fine too. The BITS constant determines the maximum hash table size. For 18
 
 
 
* this means 250KB runtime table size which is enough for files ~4MB.
 
 
 
* There is no problem for files larger than that; if we run out of table space for new
 
 
 
* codes then the same codes are emitted (uncompressed obviously)
 
 
 
*/
 
 
 
 
 
 
 
#define BITS 17                  /* Setting the number of bits to 12, 13*/
 
 
 
#define HASHING_SHIFT (BITS-8)    /* or 14 affects several constants.    */
 
 
 
#define MAX_VALUE (1 << BITS) - 1 /* Note that MS-DOS machines need to  */
 
 
 
#define MAX_CODE MAX_VALUE - 1    /* compile their code in large model if*/
 
 
 
  /* 14 bits are selected.              */
 
 
 
 
 
 
 
#if BITS == 20
 
 
 
#define TABLE_SIZE 1048583
 
 
 
#elif BITS == 19
 
 
 
#define TABLE_SIZE 524309
 
 
 
#elif BITS == 18
 
 
 
#define TABLE_SIZE 262147
 
 
 
#elif BITS == 17
 
 
 
#define TABLE_SIZE 131101
 
 
 
#elif BITS == 16
 
 
 
#define TABLE_SIZE 65543
 
 
 
#elif BITS == 15
 
 
 
#define TABLE_SIZE 32797
 
 
 
#elif BITS == 14
 
 
 
  #define TABLE_SIZE 18041        /* The string table size needs to be a */
 
 
 
  /* prime number that is somewhat larger*/
 
 
 
#elif BITS == 13                  /* than 2**BITS.                      */
 
 
 
  #define TABLE_SIZE 9029
 
 
 
#elif BITS == 12
 
 
 
  #define TABLE_SIZE 5021
 
 
 
#else
 
 
 
#error define smaller or bigger table sizes
 
 
 
#endif
 
 
 
 
 
 
 
#if (TABLE_SIZE <= MAX_VALUE)
 
 
 
#error your prime numbers need attention
 
 
 
#endif
 
 
 
 
 
 
 
#if (BITS > MAX_CODE_LEN)
 
 
 
#error BITS can only go up to a maximum
 
 
 
#endif
 
 
 
 
 
 
 
 
 
 
 
/*
 
 
 
This class does most of the job, except reading source and writing the compressed data
 
 
 
A derived class does that so that there's flexibility to read either from files or memory
 
 
 
*/
 
 
 
 
 
 
 
class CLZWImpl {
 
 
 
protected:
 
 
 
int *code_value;                  /* This is the code value array        */
 
 
 
unsigned int *prefix_code;        /* This array holds the prefix codes  */
 
 
 
unsigned char *append_character;  /* This array holds the appended chars */
 
 
 
unsigned char decode_stack[4000]; /* This array holds the decoded string */
 
 
 
unsigned char CUR_BITS;          /* ~nab: added for variable bit size */
 
 
 
/* we are processing bits but in the end of the day we do I/O in bytes */
 
 
 
int input_bit_count, output_bit_count;
 
 
 
unsigned long input_bit_buffer, output_bit_buffer;
 
 
 
 
 
 
 
public:
 
 
 
CLZWImpl() {
 
 
 
code_value = 0;
 
 
 
prefix_code = 0;
 
 
 
append_character = 0;
 
  
 +
vector<unsigned long> get_primes(unsigned long max){
 +
    vector<unsigned long> primes;
 +
    char *sieve;
 +
    sieve = new char[max/8+1];
 +
    // Fill sieve with 1
 +
    memset(sieve, 0xFF, (max/8+1) * sizeof(char));
 +
    for(unsigned long x = 2; x <= max; x++)
 +
        if(sieve[x/8] & (0x01 << (x % 8))){
 +
            primes.push_back(x);
 +
            // Is prime. Mark multiplicates.
 +
            for(unsigned long j = 2*x; j <= max; j += x)
 +
                sieve[j/8] &= ~(0x01 << (j % 8));
 +
        }
 +
    delete[] sieve;
 +
    return primes;
 
}
 
}
  
 
+
int main(void){
 
+
    vector<unsigned long> primes;
~CLZWImpl() {
+
    primes = get_primes(1000000000);
 
+
    // return 0;
if(code_value)
+
    // Print out result.
 
+
    vector<unsigned long>::iterator it;
free(code_value);
+
    for(it=primes.begin(); it < primes.end(); it++)
 
+
        cout << *it << " "<<endl;
if(prefix_code)
+
 
 
+
    cout << endl;
free(prefix_code);
+
    return 0;
 
 
if(append_character)
 
 
 
free(append_character);
 
 
 
 
}
 
}
 +
/** end of http://code.activestate.com/recipes/576559/ }}} */
  
 +
</pre>
  
 +
==== Nitin Prakash Panicker: LZW File Compression ====
  
int get_bits() { return CUR_BITS; }
+
<pre>
  
 +
Flat profile:
  
  
protected:
 
  
int Init() {
+
Each sample counts as 0.01 seconds.
  
ATLASSERT(!code_value); /* call just once */
+
  %  cumulative  self              self    total         
  
 +
time  seconds  seconds    calls  ns/call  ns/call  name   
  
 +
99.46    48.19    48.19                            CLZWCompressFile::Compress(char*, char*)
  
code_value=(int*)malloc(TABLE_SIZE*sizeof(int));
+
  0.33    48.35    0.16 17122488    9.34    9.34  CLZWCompressFile::getc_src()
  
prefix_code=(unsigned int*)malloc(TABLE_SIZE*sizeof(unsigned int));
+
  0.21    48.45    0.10  7095561    14.09    14.09  CLZWCompressFile::putc_comp(int)
  
append_character=(unsigned char*)malloc(TABLE_SIZE*sizeof(unsigned char));
+
</pre>
  
 +
==== Source Code for LZW File Compression ====
  
  
return code_value != 0 && prefix_code != 0 && append_character != 0;
 
  
}
+
[[lzw.cpp]]
 +
[[lzw.h]]
  
 +
=== Assignment 2 ===
  
 +
==== Source code for prime number generator we will be putting on the gpu ====
 +
<pre>
  
/* override these 4: read a byte from source */
+
    # include <cmath> // This library enable the use of sqrt.
 +
    # include <iostream>
 +
 
 +
    using namespace std;
 +
 
 +
    void primenum(long double); // Prototype...
 +
 
 +
    int c = 0;
 +
 
 +
    int main(){
 +
        long double x = 0;
 +
        cout<<"\n This program will generate all prime numbers up to the"
 +
        <<"\n number you have entered below...\n";
 +
        cout<<"\n Please enter a number: ";
 +
        cin>> x;
 +
        cout<<"\n Here are all the prime numbers up to "<<x<<".\n";
 +
        primenum(x); //function invocation...
 +
        cout<<endl<<"\nThere are "<<c
 +
        <<" prime numbers less than or equal to "<<x<<".\n\n";
 +
        return 0;
 +
    }
 +
    // This function will determine the primenumbers up to num.
 +
    void primenum(long double x){
 +
    bool prime = true; // Calculates the square-root of 'x'
 +
    int number2;
 +
    number2 =(int) floor (sqrt (x));
 +
    for (int i = 1; i <= x; i++){
 +
        for ( int j = 2; j <= number2; j++){
 +
            if ( i!=j && i % j == 0 ){
 +
                prime = false;
 +
                break;
 +
            }
 +
        }
 +
        if (prime){
 +
            cout <<" "<<i<<" ";
 +
            c += 1;
 +
        }
 +
        prime = true;
 +
    }
 +
    getchar();
 +
    }
  
virtual int getc_src() = 0;
+
</pre>
 +
==== Version of prime generator running on GPU ====
 +
<pre>
  
/* read a byte from compressed source (during expansion) and write to compressed output */
+
    # include <cmath> // This library enable the use of sqrt.
 +
    # include <iostream>
 +
    # include <cuda_runtime.h>
 +
 
 +
    using namespace std;
 +
 
 +
    void primenum(long double); // Prototype...
 +
 
 +
    int c = 0;
 +
 
 +
    int main(){
 +
        long double x = 0;
 +
        cout<<"\n This program will generate all prime numbers up to the"
 +
        <<"\n number you have entered below...\n";
 +
        cout<<"\n Please enter a number: ";
 +
        cin>> x;
 +
        cout<<"\n Here are all the prime numbers up to "<<x<<".\n";
 +
        primenum(x); //function invocation...
 +
        cout<<endl<<"\nThere are "<<c
 +
        <<" prime numbers less than or equal to "<<x<<".\n\n";
 +
        return 0;
 +
    }
 +
 
 +
    // This function will determine the primenumbers up to num.
 +
    void primenum(long double x){
 +
        //Array to hold generated primes on host
 +
        int *primes_h = new int[x];
 +
        //Device array to hold the primes on the device
 +
        int *primes_d = new int[x];
 +
        //allocate device memory and initialize device memory
 +
        cudaMalloc((void**)&primes_d, x * sizeof(int));
 +
        cudaMemset(&primes_d,sizeof(int),x * sizeof(int);
 +
     
 +
        //Kernal goes here
 +
        //error checking
 +
     
 +
        //copy the array holding primes from device to host
 +
        cudaMemcpy(primes_h, primes_d, x * sizeof(int), cudaMemcpyDeviceToHost);
 +
     
 +
        //display the primes
 +
        for(int i=0; i<x ; i++){
 +
            cout<<primes_h[i]<<endl;
 +
        }
 +
     
 +
        //free allocated memory
 +
        delete [] primes_h;
 +
        cudaFree(primes_d);
 +
     
 +
        getchar();
 +
    }
  
virtual int getc_comp() = 0;
+
</pre>
 +
==== Almost Final version ====
 +
<pre>
 +
# include <cmath> // This library enable the use of sqrt.
  
/* write a byte to compressed output */
+
    # include <iostream>
  
virtual int putc_comp(int ch) = 0;
+
# include <ctime>
  
/* write a byte to expanded output */
+
#include<iomanip>
  
virtual int putc_out(int ch) = 0;
+
#include<cstdlib>
  
 +
    # include <cuda_runtime.h>
  
 +
//#include <times.h>
  
/*
+
 
  
** This is the compression routine.  The code should be a fairly close
+
    using namespace std;
  
** match to the algorithm accompanying the article.
+
  
**
+
inline clock_t getMilliSecs() {
  
*/
+
return clock() / (CLOCKS_PER_SEC / 1000);
  
 +
}
  
  
void compress()
 
  
{
+
__global__ void primegen(bool prime, int number2,int x,int *primes_d)
  
unsigned int next_code;
+
{
  
unsigned int character;
+
      int c = 0;
  
unsigned int string_code;
 
  
unsigned int index;
 
  
unsigned int bit_limit;
+
for (int i = 1; i <= x; i++)
  
int i;
+
{
 
 
 
 
 
 
ATLASSERT(code_value); /* initialized? */
 
 
 
 
 
 
 
CUR_BITS = MIN_CODE_LEN;
 
 
 
bit_limit = CURRENT_MAX_CODES(CUR_BITS) - 1;
 
 
 
output_bit_count=0;
 
 
 
output_bit_buffer=0L;
 
 
 
 
 
 
 
ATLASSERT(256==FIRST_CODE);
 
 
 
next_code=FIRST_CODE;      /* Next code is the next available string code*/
 
 
 
for (i=0;i<TABLE_SIZE;i++)  /* Clear out the string table before starting */
 
 
 
code_value[i]=-1;
 
  
 +
        for ( int j = 2; j <= number2; j++)
  
 +
{
  
  string_code=getc_src();      /* Get the first code                        */
+
            if ( i!=j && i % j == 0 )
  
  if(-1 == string_code)
+
{
  
  return; /* empty file or error */
+
                prime = false;
  
 +
                break;
  
 +
            }
  
/*
+
        }
  
** This is the main loop where it all happens.  This loop runs util all of
+
        if (prime)
 
 
** the input has been exhausted.  Note that it stops adding codes to the
 
 
 
** table after all of the possible codes have been defined.
 
 
 
*/
 
 
 
  while ((character=getc_src()) != -1)
 
 
 
  {
 
 
 
    index=find_match(string_code,character);/* See if the string is in */
 
 
 
    if (code_value[index] != -1)            /* the table.  If it is,  */
 
 
 
      string_code=code_value[index];        /* get the code value.  If */
 
 
 
    else                                    /* the string is not in the*/
 
 
 
    {                                      /* table, try to add it.  */
 
 
 
      if (next_code <= MAX_CODE)
 
 
 
      {
 
 
 
code_value[index]=next_code++;
 
 
 
prefix_code[index]=string_code;
 
 
 
append_character[index]=character;
 
 
 
      }
 
 
 
 
 
 
 
/* are we using enough bits to write out this code word? */
 
 
 
if(string_code >= bit_limit && CUR_BITS < BITS)
 
  
 
{
 
{
  
/* mark need for bigger code word with all ones */
+
          primes_d[c]=i;
  
output_code(bit_limit);
+
            c += 1;
  
CUR_BITS++;
+
        }
  
bit_limit = (CURRENT_MAX_CODES(CUR_BITS) - 1);
+
        prime = true;
  
}
+
    }
  
 +
  
 +
}
  
ATLASSERT(string_code < bit_limit);
+
 
  
 +
    void primenum(long double); // Prototype...
  
 +
 
  
      output_code(string_code); /* When a string is found  */
+
   
  
      string_code=character;            /* that is not in the table*/
+
 
  
     }                                  /* I output the last string*/
+
     int main()
  
  }                                    /* after adding the new one*/
+
{
  
/*
+
        long double x = 0;
  
** End of the main loop.
+
        cout<<"\n This program will generate all prime numbers up to the"<<"\n number you have entered below...\n";
  
*/
+
        cout<<"\n Please enter a number: ";
  
 +
        cin>> x;
  
 +
        cout<<"\n Here are all the prime numbers up to "<<x<<".\n";
  
  output_code(string_code); /* Output the last code              */
+
        primenum(x); //function invocation...
  
  output_code(-1);          /* This code flushes the output buffer*/
+
        //cout<<endl<<"\nThere are "<<c
  
}
+
        //<<" prime numbers less than or equal to "<<x<<".\n\n";
  
 +
        return 0;
  
 +
    }
  
/*
+
 
  
** This is the hashing routine. It tries to find a match for the prefix+char
+
    // This function will determine the primenumbers up to num.
  
** string in the string table.  If it finds it, the index is returned.  If
+
    void primenum(long double x)
  
** the string is not found, the first available index in the string table is
+
{
  
** returned instead.
+
bool prime = true;
  
*/
+
//struct tms start_time, stop_time;
  
int find_match(unsigned int hash_prefix,unsigned int hash_character)
+
  int number2;
  
{
+
  number2 =(int) floor (sqrt (x));
  
int index;
+
  clock_t start = getMilliSecs();
  
int offset;
+
        //Array to hold generated primes on host
  
 +
        int *primes_h = new int[(int)x];
  
 +
        //Device array to hold the primes on the device
  
  index = (hash_character << HASHING_SHIFT) ^ hash_prefix;
+
        int *primes_d = new int[(int)x];
  
  if (index == 0)
+
        //allocate device memory and initialize device memory
  
    offset = 1;
+
        cudaMalloc((void**)&primes_d, (int)x * sizeof(int));
  
  else
+
// cudaMalloc((void**)&c_d, sizeof(int));
  
    offset = TABLE_SIZE - index;
+
        cudaMemset(&primes_d,0,x * sizeof(int));
  
  while (1)
+
        //error checking
  
  {
+
        cudaError_t error ;
  
    if (code_value[index] == -1)
+
        //Kernal goes here
  
      return(index);
+
primegen<<<1,1>>>(prime,number2,(int)x,primes_d);
  
    if (prefix_code[index] == hash_prefix &&
+
  
append_character[index] == hash_character)
+
// extract error code from the kernel's execution
  
      return(index);
+
        error = cudaGetLastError();
  
    index -= offset;
+
        if (error != cudaSuccess) {
  
    if (index < 0)
+
                cout << cudaGetErrorString(error) << endl;
  
      index += TABLE_SIZE;
+
        }
  
  }
+
     
  
}
+
        //copy the array holding primes from device to host
  
 +
        error =cudaMemcpy(primes_h, primes_d, ((int)x) * sizeof(int), cudaMemcpyDeviceToHost);
  
 +
   
  
/*
+
        if (error != cudaSuccess) {
  
**  This is the expansion routine.  It takes an LZW format file, and expands
+
                cout << cudaGetErrorString(error) << endl;
  
**  it to an output file.  The code here should be a fairly close match to
+
        }
  
**  the algorithm in the accompanying article.
+
// cudaMemcpy(c_h, c_d, sizeof(int), cudaMemcpyDeviceToHost);
  
*/
+
        //display the primes
  
 +
for(int i=0; i<(int)x ; i++){
  
 +
if(primes_h[i]>=2 && primes_h[i]<=(int)x){
  
void expand()
+
cout<<primes_h[i]<<endl;
  
{
+
}
 
 
unsigned int next_code;
 
 
 
unsigned int new_code;
 
 
 
unsigned int old_code;
 
 
 
int character;
 
 
 
unsigned char *string;
 
 
 
unsigned int bit_limit;
 
 
 
 
 
 
 
ATLASSERT(code_value); /* initialized? */
 
 
 
 
 
 
 
CUR_BITS = MIN_CODE_LEN;
 
 
 
bit_limit = CURRENT_MAX_CODES(CUR_BITS) - 1;
 
 
 
input_bit_count=0;
 
 
 
input_bit_buffer=0L;
 
 
 
 
 
 
 
// @@@ what if we pass uncompressed file to decode?
 
 
 
 
 
 
 
  next_code=FIRST_CODE;        /* This is the next available code to define */
 
 
 
 
 
 
 
  old_code=input_code();      /* Read in the first code, initialize the */
 
 
 
  if(-1 == old_code)
 
 
 
  return; /* read error? */
 
  
  character=old_code;          /* character variable, and send the first */
+
        }
  
  if(putc_out(old_code)==-1)   /* code to the output file                */
+
      cout << "Elapsed time: " << (getMilliSecs() - start) << "ms" << endl;
  
  return; /* write error */
+
      // cout<< "time: "<< (stop_s-start_s)/double(CLOCKS_PER_SEC)<<endl;
  
/*
+
        //free allocated memory
  
**  This is the main expansion loop.  It reads in characters from the LZW file
+
  
**  until it sees the special code used to inidicate the end of the data.
+
        delete [] primes_h;
  
*/
+
        cudaFree(primes_d);
  
  while ((new_code=input_code()) != (-1))
+
     
  
  {
+
        getchar();
 
 
  /* look for code length increase marker */
 
 
 
  if(bit_limit == new_code && CUR_BITS < BITS)
 
 
 
  {
 
 
 
  CUR_BITS++;
 
 
 
  bit_limit = CURRENT_MAX_CODES(CUR_BITS) - 1;
 
 
 
 
 
 
 
  new_code=input_code();
 
 
 
  ATLASSERT(new_code != -1); /* must be read error? */
 
 
 
  if(new_code == -1)
 
 
 
  break;
 
 
 
  }
 
 
 
 
 
 
 
ATLASSERT(new_code < bit_limit);
 
 
 
 
 
 
 
/*
 
 
 
** This code checks for the special STRING+CHARACTER+STRING+CHARACTER+STRING
 
 
 
** case which generates an undefined code.  It handles it by decoding
 
 
 
** the last code, and adding a single character to the end of the decode string.
 
 
 
*/
 
 
 
    if (new_code>=next_code)
 
 
 
    {
 
 
 
      *decode_stack=character;
 
 
 
      string=decode_string(decode_stack+1,old_code);
 
  
 
     }
 
     }
 +
</pre>
  
/*
+
=== Assignment 3 ===
 
+
==== Cuda Version:First Attempt ====
** Otherwise we do a straight decode of the new code.
 
 
 
*/
 
 
 
    else
 
 
 
      string=decode_string(decode_stack,new_code);
 
 
 
/*
 
 
 
** Now we output the decoded string in reverse order.
 
 
 
*/
 
 
 
    character=*string;
 
 
 
    while (string >= decode_stack)
 
 
 
      putc_out(*string--);
 
 
 
/*
 
 
 
** Finally, if possible, add a new code to the string table.
 
 
 
*/
 
 
 
    if (next_code <= MAX_CODE)
 
 
 
    {
 
 
 
      prefix_code[next_code]=old_code;
 
 
 
      append_character[next_code]=character;
 
 
 
      next_code++;
 
 
 
    }
 
 
 
    old_code=new_code;
 
 
 
  }
 
 
 
}
 
  
 +
<pre>
  
 +
# include <cmath> // This library enable the use of sqrt.
  
/*
+
    # include <iostream>
  
** This routine simply decodes a string from the string table, storing
+
# include <ctime>
  
** it in a buffer.  The buffer can then be output in reverse order by
+
#include<iomanip>
  
** the expansion program.
+
#include<cstdlib>
  
*/
+
    # include <cuda_runtime.h>
  
/* ~nab: these char* aren't a risk for unicode; we are reading bytes */
+
//#include <times.h>
  
unsigned char *decode_string(unsigned char *buffer,unsigned int code)
+
 
  
{
+
    using namespace std;
  
int i;
+
  
 +
inline clock_t getMilliSecs() {
  
 
+
return clock() / (CLOCKS_PER_SEC / 1000);
  i=0;
 
 
 
  while (code >= FIRST_CODE)
 
 
 
  {
 
 
 
    *buffer++ = append_character[code];
 
 
 
    code=prefix_code[code];
 
 
 
i++;
 
 
 
ATLASSERT(i < sizeof(decode_stack)); /* buffer overrun if it blows, increase stack size! */
 
 
 
  }
 
 
 
  *buffer=code;
 
 
 
  return(buffer);
 
 
 
}
 
 
 
 
 
 
 
/*
 
 
 
** The following two routines are used to output variable length
 
 
 
** codes.  They are written strictly for clarity, and are not
 
 
 
** particularyl efficient.
 
 
 
 
 
 
 
  ~nab: there's room for improvement in these I/O functions eg work in DWORDS instead of bytes
 
 
 
*/
 
 
 
 
 
 
 
unsigned int input_code()
 
 
 
{
 
 
 
int c;
 
 
 
unsigned int return_value;
 
 
 
//static int input_bit_count=0;
 
 
 
//static unsigned long input_bit_buffer=0L;
 
 
 
 
 
 
 
  while (input_bit_count <= 24)
 
 
 
  {
 
 
 
if ((c = getc_comp()) == -1)
 
 
 
break;
 
 
 
 
 
 
 
    input_bit_buffer |=
 
 
 
(unsigned long) c << (24-input_bit_count);
 
 
 
    input_bit_count += 8;
 
 
 
  }
 
 
 
 
 
 
 
  if(input_bit_count < CUR_BITS) {
 
 
 
  ATLASSERT(!input_bit_buffer);
 
 
 
return -1; /* EOF */
 
  
 
}
 
}
Line 982: Line 600:
  
  
  return_value=input_bit_buffer >> (32-CUR_BITS);
+
__global__ void primegen(bool prime, int number2,int x,int *primes_d)
  
  input_bit_buffer <<= CUR_BITS;
+
{
  
  input_bit_count -= CUR_BITS;
+
      int c = 0;
  
 +
  int idx = blockIdx.x * blockDim.x + threadIdx.x;
  
 +
 
  
  ATLASSERT(return_value < (1UL << CUR_BITS));
+
  for ( int i=1; i <= x; i++)
  
  return(return_value);
+
{
  
}
+
if( i!= idx && i%idx == 0 )
  
 +
{
  
 +
prime = false;
  
/* bits are written outside normal byte boundaries, hence the need for keeping old values */
+
break;
  
void output_code(unsigned int code)
+
}
  
{
+
  
//static int output_bit_count=0;
+
if(prime)
  
//static unsigned long output_bit_buffer=0L;
+
{
  
 +
primes_d[c]=i;
  
 +
c += 1;
  
ATLASSERT(output_bit_count < 8); /* leftovers */
+
}
 
 
ATLASSERT(CUR_BITS + output_bit_count <= 32);
 
 
 
/*codes <256 are possible for single characters, zero bytes etc*/
 
 
 
 
 
 
 
if(-1 == code) {
 
 
 
/* pad remaining zeros and flush the last byte */
 
 
 
if(output_bit_count) {
 
 
 
output_bit_buffer >>= 24;
 
  
ATLASSERT((output_bit_buffer & 0xFF) == output_bit_buffer);
+
prime = true;
 
 
putc_comp(output_bit_buffer);
 
 
 
 
 
 
 
output_bit_count = 0;
 
 
 
output_bit_buffer = 0; /* in case some eejit calls us again */
 
  
 
}
 
}
  
 +
  
 +
  
return;
+
}
  
}
+
 
  
  
  
ATLASSERT(code < (1UL << CUR_BITS));
+
/*for (int i = 1; i <= x; i++)
  
 +
{
  
 +
        for ( int j = 2; j <= number2; j++)
  
/* sends new bytes near the top (MSB) */
+
{
  
  output_bit_buffer |= (unsigned long) code << (32-CUR_BITS-output_bit_count);
+
            if ( i!=j && i % j == 0 )
  
  output_bit_count += CUR_BITS;
+
{
  
  while (output_bit_count >= 8)
+
                prime = false;
  
  {
+
                break;
  
/* no check for error but if there was a problem we'd know from the time we wrote the identifier */
+
            }
  
    putc_comp(output_bit_buffer >> 24);
+
        }
  
    output_bit_buffer <<= 8;
+
        if (prime)
  
    output_bit_count -= 8;
+
{
 
 
  }
 
 
 
}
 
 
 
}; /* CLZWImpl */
 
 
 
 
 
 
 
/* example derived class using C buffered I/O functions */
 
  
class CLZWCompressFile : public CLZWImpl {
+
          primes_d[c]=i;
  
public:
+
            c += 1;
  
CLZWCompressFile() {
+
        }
  
io_file = 0;
+
        prime = true;
  
lzw_file = 0;
+
  
};
+
    } */
  
 +
  
  
~CLZWCompressFile() {
 
  
ATLASSERT(!io_file);
+
 
  
ATLASSERT(!lzw_file);
+
    void primenum(long double); // Prototype...
  
};
+
 
  
 +
  
 +
 
  
int AnyIOErrors() {return io_error; }
+
    int main()
 
 
 
 
 
 
// @@@ these char* should be changed for unicode builds
 
 
 
unsigned int Compress(char* input_file_name, char* to_name)
 
  
 
{
 
{
  
ATLASSERT(input_file_name && *input_file_name);
+
        long double x = 0;
  
ATLASSERT(to_name && *to_name);
+
        cout<<"\n This program will generate all prime numbers up to the"<<"\n number you have entered below...\n";
  
ATLASSERT(strcmp(to_name, input_file_name));
+
        cout<<"\n Please enter a number: ";
  
 +
        cin>> x;
  
 +
        cout<<"\n Here are all the prime numbers up to "<<x<<".\n";
  
io_error = 1;
+
        primenum(x); //function invocation...
  
 +
        //cout<<endl<<"\nThere are "<<c
  
 +
        //<<" prime numbers less than or equal to "<<x<<".\n\n";
  
if(!code_value)
+
        return 0;
  
if(!Init())
+
    }
  
return 0; /* rare memory error */
+
 
  
 +
    // This function will determine the primenumbers up to num.
  
 +
    void primenum(long double x)
  
u_comp = 0;
+
{
  
u_io = 0;
+
int  n = x;
  
io_file=fopen(input_file_name,"rb");
+
  int  d;
  
if(io_file) {
+
bool prime = true;
  
lzw_file=fopen(to_name,"wb");
+
//struct tms start_time, stop_time;
  
if(lzw_file) {
+
  int number2;
  
/* write LZW identifier L+starting bytes */
+
  number2 =(int) floor (sqrt (x));
  
putc('L', lzw_file);
+
  clock_t start = getMilliSecs();
  
if(putc(MIN_CODE_LEN, lzw_file) == MIN_CODE_LEN) {
+
 
  
compress();
+
  cudaDeviceProp prop;
  
io_error = ferror(lzw_file) || ferror(io_file);
+
        cudaGetDevice(&d);
  
if(!io_error)
+
        cudaGetDeviceProperties(&prop, d);
  
ATLASSERT(u_comp <= u_io); /* this is bound to bomb every now and then, no compression! */
+
        int nThreads = prop.maxThreadsDim[0];
  
}
+
        int n_max = nThreads * prop.maxGridSize[0];
  
fclose(lzw_file);
+
        if ( n> n_max) {
  
lzw_file = 0;
+
                n = n_max;
  
}
+
                cout << "n reduced to " << n << endl;
  
 +
        }
  
 +
 
  
fclose(io_file);
+
        //Array to hold generated primes on host
  
io_file = 0;
+
        int *primes_h = new int[(int)x];
  
}
+
  
 +
        //Device array to hold the primes on the device
  
 +
        int *primes_d = new int[(int)x];
  
return u_comp;
+
  
}
+
        //allocate device memory and initialize device memory
  
 +
        cudaMalloc((void**)&primes_d, (int)x * sizeof(int));
  
 +
  
unsigned int Expand(char* lzw_name, char* to_name)
+
// cudaMalloc((void**)&c_d, sizeof(int));
  
{
+
        cudaMemset(&primes_d,0,x * sizeof(int));
 
 
ATLASSERT(lzw_name && *lzw_name);
 
 
 
ATLASSERT(to_name && *to_name);
 
  
ATLASSERT(strcmp(to_name, lzw_name));
+
  
 +
        //error checking
  
 +
        cudaError_t error ;
  
io_error = 1;
+
  
 +
        //Kernal goes here
  
 +
primegen<<<(n + nThreads - 1) / nThreads, nThreads>>>(prime,number2,(int)x,primes_d);
  
if(!code_value)
+
  
if(!Init())
+
// extract error code from the kernel's execution
  
return 0; /* rare memory error */
+
  
 +
        error = cudaGetLastError();
  
 +
        if (error != cudaSuccess) {
  
u_comp = 0;
+
                cout << cudaGetErrorString(error) << endl;
  
u_io = 0;
+
        }
  
lzw_file=fopen(lzw_name,"rb");
+
     
  
if(lzw_file) {
+
        //copy the array holding primes from device to host
  
/* check LZW identifier L+starting bytes */
+
  
int ch1 = getc(lzw_file);
+
        error =cudaMemcpy(primes_h, primes_d, ((int)x) * sizeof(int), cudaMemcpyDeviceToHost);
  
int ch2 = getc(lzw_file);
+
   
  
if('L' == ch1 && MIN_CODE_LEN==ch2) {
+
        if (error != cudaSuccess) {
  
io_file=fopen(to_name,"wb");
+
                cout << cudaGetErrorString(error) << endl;
  
if(io_file) {
+
        }
  
expand();
+
// cudaMemcpy(c_h, c_d, sizeof(int), cudaMemcpyDeviceToHost);
  
io_error = ferror(lzw_file) || ferror(io_file);
+
        //display the primes
  
 +
for(int i=0; i<(int)x ; i++){
  
 +
if(primes_h[i]>=2 && primes_h[i]<=(int)x){
  
fclose(io_file);
+
cout<<primes_h[i]<<endl;
 
 
io_file = 0;
 
 
 
}
 
  
 
}
 
}
  
 +
        }
  
 +
      cout << "Elapsed time: " << (getMilliSecs() - start) << "ms" << endl;
  
fclose(lzw_file);
+
      // cout<< "time: "<< (stop_s-start_s)/double(CLOCKS_PER_SEC)<<endl;
  
lzw_file = 0;
+
        //free allocated memory
  
}
+
  
 +
        delete [] primes_h;
  
 +
        cudaFree(primes_d);
  
return u_io;
+
     
  
}
+
        getchar();
  
 +
    }
  
 +
</pre>
 +
==== Conclusion: Logical Error ====
  
protected:
+
[[Image:gpuA3error.png|thumb|widthpx| ]]
  
/* -1 return indicates either EOF or some IO error */
+
The prime number generated seems to have run into some logical error. It does not generate the prime numbers correctly. Instead spits out all numbers.
  
virtual int getc_src() {
+
==== Cuda Version: Attempt Two ====
 +
Gives a run time error "invalid argument". Logical error still persists.
  
ATLASSERT(io_file);
+
==== Final Cuda version ====
 +
<pre>
 +
#include <cstdio>
 +
#include <cstdlib>
 +
#include <iostream>
 +
#include <ctime>
 +
#include <cuda_runtime.h>
  
int ch = getc(io_file);
+
using namespace std;
  
if(EOF == ch)
+
/**
 +
* This macro checks return value of the CUDA runtime call and exits
 +
* the application if the call failed.
 +
*/
 +
#define CUDA_CHECK_RETURN(value) {                                            \
 +
    cudaError_t _m_cudaStat = value;                                        \
 +
    if (_m_cudaStat != cudaSuccess) {                                        \
 +
        fprintf(stderr, "Error %s at line %d in file %s\n",                    \
 +
                cudaGetErrorString(_m_cudaStat), __LINE__, __FILE__);        \
 +
        exit(1);                                                            \
 +
    } }
  
return -1;
+
/**
 +
* Kernel code to generate and detect primes
 +
*/
 +
__global__ void prime(int *num, int blockNum, int threadNum, int size) {
 +
    const int tid = blockIdx.x * blockDim.x + threadIdx.x;
 +
    const int bid = blockIdx.y * blockDim.y + threadIdx.y;
 +
    __syncthreads();
  
 +
    /**
 +
    * Generate prime numbers and store them in the array.
 +
    * The first element is always 2
 +
    */
 +
    if(tid == 0) {
 +
        num[tid] = 2;
 +
    } else {
 +
        num[tid] = 2 * tid + 1;
 +
    }
  
 +
    int tmp = bid * threadNum + tid;
  
u_io++;
+
    int step1 = 2 * tmp + 3;
 +
    int step2 = tmp + 1;
  
return ch;
+
    while(tmp < size) {
 +
        int i = 1;
 +
        /**
 +
        * Check if an element is not prime, if it isn't set it to 0.
 +
        */
 +
        while((step1 * i + step2) < size) {
 +
            num[step1 * i + step2] = 0;
 +
            i++;
 +
        }
 +
        tmp += blockNum * threadNum;
 +
        __syncthreads();
 +
    }
 +
}
  
}
+
int main(int argc, char* argv[]) {
 +
    if(argc != 2) {
 +
        cout << "Incorrect no of arguments" << endl;
 +
        return 1;
 +
    }
 +
    int n = atoi(argv[1]);
  
virtual int getc_comp() {
+
    /**
 +
    * variable declarations
 +
    */
 +
    int *device;
 +
    int host[n];
 +
    int d;
 +
    cudaDeviceProp prop;
  
ATLASSERT(lzw_file);
+
    /**
 +
    * Get the properties of the device in use
 +
    */
 +
    cudaGetDevice(&d);
 +
    cudaGetDeviceProperties(&prop, d);
 +
    int numberOfBlocks = 8;
 +
    int maxThreadsPerBlock = prop.maxThreadsPerBlock;
 +
    int numberOfThreads = maxThreadsPerBlock/numberOfBlocks;
  
int ch = getc(lzw_file);
+
    /**
 +
    * Start timer
 +
    */
 +
    clock_t cb, ce;
 +
    cb = clock();
  
if(EOF == ch)
+
    /**
 +
    * Allocate memory on the device
 +
    */
 +
    CUDA_CHECK_RETURN(cudaMalloc((void**) &device, sizeof(int) * n));
  
return -1;
+
    /**
 +
    * Call kernel with appropriate grid and thread size
 +
    */
 +
    prime<<<numberOfBlocks, numberOfThreads>>>(device, numberOfBlocks, numberOfThreads, n);
  
 +
    /**
 +
    * Copy results back to host
 +
    */
 +
    CUDA_CHECK_RETURN(cudaMemcpy(&host, device, sizeof(int) * n, cudaMemcpyDeviceToHost));
  
 +
    /**
 +
    * Free memory on device
 +
    */
 +
    CUDA_CHECK_RETURN(cudaFree(device));
  
u_comp++;
+
    /**
 +
    * Output values
 +
    */
 +
    for (int i = 0; i < n; i++)
 +
        if (host[i] != 0)
 +
            cout << host[i] << endl;
  
return ch;
+
    /**
 
+
    * Stop timer
}
+
    */
 
+
    ce = clock();
virtual int putc_comp(int ch) {
+
    cout << "Prime generation - took " << double(ce - cb)/CLOCKS_PER_SEC << " seconds" << endl;
 
+
}
ATLASSERT(lzw_file);
 
 
 
ATLASSERT(ch >= 0 && ch < 256);
 
 
 
int ret = putc(ch, lzw_file);
 
 
 
 
 
 
 
if(ret != EOF) {
 
 
 
ATLASSERT(ret == ch);
 
 
 
u_comp++;
 
 
 
}
 
 
 
else
 
 
 
ret = -1;
 
 
 
 
 
 
 
return ret;
 
 
 
}
 
 
 
virtual int putc_out(int ch) {
 
 
 
ATLASSERT(io_file);
 
 
 
ATLASSERT(ch >= 0 && ch < 256);
 
 
 
int ret = putc(ch, io_file);
 
 
 
 
 
 
 
if(ret != EOF)
 
 
 
u_io++;
 
 
 
else
 
 
 
ret = -1;
 
 
 
 
 
 
 
return ret;
 
 
 
}
 
 
 
 
 
 
 
FILE* io_file;
 
 
 
FILE *lzw_file;
 
 
 
int io_error;
 
 
 
public:
 
 
 
unsigned long u_io, u_comp; /* bytes read and written */
 
 
 
};
 
 
 
 
 
 
 
// @@@ could have a generic one on IStream, CreateStreamOnHGlobal/SHCreateStreamOnFile
 
 
 
 
 
 
 
#endif /* UPRIGHT_LZW_H */
 
 
</pre>
 
</pre>
----
+
[[Image:manualDelete.png|thumb|200px|Manual Delete Warning]]
 +
===== Final version's errors, warnings and observations =====
 +
* If a number over 515 is entered as the launch argument, the program will display random values at the end of the list of prime numbers
 +
* When attempting to delete the host array manually in the program, a warning is displayed
 +
[[Image:ManualCrash.png|thumb|200px|Manual Delete Crash]]
 +
* The program crashes at the end if the host array is manually deleted
  
=== Assignment 2 ===
+
===== Successful run of Prime generation =====
=== Assignment 3 ===
+
[[Image:PrimeSuccessfulRun.png]]

Latest revision as of 15:55, 12 April 2013


GPU610/DPS915 | Student List | Group and Project Index | Student Resources | Glossary

Team: M-N-M

Team Members

  1. Muhammad Ahsan
  2. Nitin Prakash Panicker
  3. Mohamed Baig


Email All

Potential Projects

Projects
Project Name Project Description Status
C Compiler Take the compilation process and transfer it to the GPU failed
Galactic Collision Simulation A 2D simulation of two galaxies colliding, with fully simulated gravity effects. cannot benefit from parallel computing,already fast enough
Isomorphism of graphs Check if two graphs are isomorphic in nature. This is a very straight forward program. failed
Image Processing Mathematical operations applied to images for colour negation, rotation, blurring effects, etc. scrapped
Facial Recognition system Speed up time taken to match face with database already CUDA enabled
Steganography Speed up the process of encrypting one type of file into another Profiled
Prime number generator Generate prime numbers Profiled
LZW File compression Compress files using Lempel-Ziv-Welch algorithm Profiled

Progress

Assignment 1

Mohamed Baig: Steganography using Steghide

Steghide has certain dependencies that it uses to complete its function.
Dependencies:
Makefile changes made
  • libmash
  • libcrypt
  • libjpeg
  • zlib
  • Ran the Configure file to see if I have all the Dependencies
  • Installed the all the dependencies
  • Ran Configure again to generate Makefile in the src folder
  • Altered the Makefile to enable profiling
  • Altered some source files to avoid errors

AuSampleValues.cc

#include "AuSampleValues.h"

// AuMuLawSampleValue
template <> //My change
const BYTE AuMuLawSampleValue::MinValue = 0 ;
template <> //My change
const BYTE AuMuLawSampleValue::MaxValue = BYTE_MAX ;

// AuPCM8SampleValue
template <> //My change
const SBYTE AuPCM8SampleValue::MinValue = SBYTE_MIN ;
template <> //My change
const SBYTE AuPCM8SampleValue::MaxValue = SBYTE_MAX ;

// AuPCM16SampleValue
template <> //My change
const SWORD16 AuPCM16SampleValue::MinValue = SWORD16_MIN ;
template <> //My change
const SWORD16 AuPCM16SampleValue::MaxValue = SWORD16_MAX ;

// AuPCM32SampleValue
template <> //My change
const SWORD32 AuPCM32SampleValue::MinValue = SWORD32_MIN ;
template <> //My change
const SWORD32 AuPCM32SampleValue::MaxValue = SWORD32_MAX ;

AuData.h

#ifndef SH_AUDATA_H
#define SH_AUDATA_H

#include "BinaryIO.h"
#include "AudioData.h"

// AuMuLawAudioData
typedef AudioDataImpl<AuMuLaw,BYTE> AuMuLawAudioData ;
template <> //My change
inline BYTE AuMuLawAudioData::readValue (BinaryIO* io) const { return (io->read8()) ; }
template <> //My change
inline void AuMuLawAudioData::writeValue (BinaryIO* io, BYTE v) const { io->write8(v) ; }

// AuPCM8AudioData
typedef AudioDataImpl<AuPCM8,SBYTE> AuPCM8AudioData ;
template <> //My change
inline SBYTE AuPCM8AudioData::readValue (BinaryIO* io) const { return ((SBYTE) io->read8()) ; }
template <> //My change
inline void AuPCM8AudioData::writeValue (BinaryIO* io, SBYTE v) const { io->write8((BYTE) v) ; }

// AuPCM16AudioData
typedef AudioDataImpl<AuPCM16,SWORD16> AuPCM16AudioData ;
template <> //My change
inline SWORD16 AuPCM16AudioData::readValue (BinaryIO* io) const { return ((SWORD16) io->read16_be()) ; }
template <> //My change
inline void AuPCM16AudioData::writeValue (BinaryIO* io, SWORD16 v) const { io->write16_be((UWORD16) v) ; }

// AuPCM32AudioData
typedef AudioDataImpl<AuPCM32,SWORD32> AuPCM32AudioData ;
template <> //My change
inline SWORD32 AuPCM32AudioData::readValue (BinaryIO* io) const { return ((SWORD32) io->read32_be()) ; }
template <> //My change
inline void AuPCM32AudioData::writeValue (BinaryIO* io, SWORD32 v) const { io->write32_be((UWORD32) v) ; }

#endif // ndef SH_AUDATA_H
  • The result of embedding kilobytes of text data into an image
Flat profile:

Each sample counts as 0.01 seconds.
  %   cumulative   self              self     total          
 time   seconds   seconds    calls   s/call   s/call  name   
 13.38      0.21     0.21  1318276     0.00     0.00  Selector::idxX(unsigned int, unsigned int, unsigned int*) const
 11.47      0.39     0.18  4054789     0.00     0.00  Vertex::getDegree() const
  9.55      0.54     0.15   659139     0.00     0.00  Selector::calculate(unsigned int)
  7.64      0.66     0.12   659141     0.00     0.00  JpegFile::getEmbeddedValue(unsigned int) const
  7.01      0.77     0.11   659139     0.00     0.00  __gnu_cxx::hashtable<std::pair<unsigned int const, unsigned int>, unsigned int, __gnu_cxx::hash<unsigned int>, std::_Select1st<std::pair<unsigned int const, unsigned int> >, std::equal_to<unsigned int>, std::allocator<unsigned int> >::resize(unsigned long)
  6.37      0.87     0.10   328293     0.00     0.00  JpegFile::getSampleValue(unsigned int) const
  5.73      0.96     0.09        1     0.09     0.09  Selector::~Selector()
  3.82      1.02     0.06        1     0.06     0.09  JpegFile::read(BinaryIO*)
  • The result of attempting to embed 1.7 GB of data into an image
Flat profile:

Each sample counts as 0.01 seconds.
  %   cumulative   self              self     total          
 time   seconds   seconds    calls   s/call   s/call  name   
 54.43     21.52    21.52 1192388169     0.00     0.00  BitString::_append(bool)
 16.79     28.15     6.64 593200712     0.00     0.00  BitString::operator[](unsigned long) const
  9.30     31.83     3.68 74898412     0.00     0.00  BitString::append(unsigned char, unsigned short)
  4.78     33.72     1.89        3     0.63     6.41  BitString::append(BitString const&)
  3.50     35.10     1.39                             BitString::BitString(unsigned long)
  1.91     35.86     0.76                             BitString::clear()
  1.29     36.37     0.51        1     0.51    37.26  Embedder::Embedder()
  1.20     36.84     0.48 37823336     0.00     0.00  BinaryIO::eof() const

Muhammad Ahsan: Prime Number Generator( 1,000,000,000 primes)

Flat profile

Each sample counts as 0.01 seconds.
  %   cumulative   self              self     total           
 time   seconds   seconds    calls  Ts/call  Ts/call  name    
100.00     53.83    53.83                             get_primes(unsigned long)
  0.00     53.83     0.00       27     0.00     0.00  void std::vector<unsigned long, std::allocator<unsigned long> >::_M_emplace_back_aux<unsigned long const&>(unsigned long const&&&)
  0.00     53.83     0.00        1     0.00     0.00  _GLOBAL__sub_I__Z10get_primesm

/** {{{ http://code.activestate.com/recipes/576559/ (r2) */
/*
 Copyright (c) 2008 Florian Mayer

 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
 in the Software without restriction, including without limitation the rights
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 copies of the Software, and to permit persons to whom the Software is
 furnished to do so, subject to the following conditions:

 The above copyright notice and this permission notice shall be included in
 all copies or substantial portions of the Software.

 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 THE SOFTWARE.
*/

#include <iostream>
#include <vector>
#include <string.h>

using namespace std;

vector<unsigned long> get_primes(unsigned long max){
    vector<unsigned long> primes;
    char *sieve;
    sieve = new char[max/8+1];
    // Fill sieve with 1 
    memset(sieve, 0xFF, (max/8+1) * sizeof(char));
    for(unsigned long x = 2; x <= max; x++)
        if(sieve[x/8] & (0x01 << (x % 8))){
            primes.push_back(x);
            // Is prime. Mark multiplicates.
            for(unsigned long j = 2*x; j <= max; j += x)
                sieve[j/8] &= ~(0x01 << (j % 8));
        }
    delete[] sieve;
    return primes;
}

int main(void){
    vector<unsigned long> primes;
    primes = get_primes(1000000000);
    // return 0;
    // Print out result.
    vector<unsigned long>::iterator it;
    for(it=primes.begin(); it < primes.end(); it++)
        cout << *it << " "<<endl;
   
    cout << endl;
    return 0;
}
/** end of http://code.activestate.com/recipes/576559/ }}} */

Nitin Prakash Panicker: LZW File Compression


Flat profile:



Each sample counts as 0.01 seconds.

  %   cumulative   self              self     total           

 time   seconds   seconds    calls  ns/call  ns/call  name    

 99.46     48.19    48.19                             CLZWCompressFile::Compress(char*, char*)

  0.33     48.35     0.16 17122488     9.34     9.34  CLZWCompressFile::getc_src()

  0.21     48.45     0.10  7095561    14.09    14.09  CLZWCompressFile::putc_comp(int)

Source Code for LZW File Compression

lzw.cpp lzw.h

Assignment 2

Source code for prime number generator we will be putting on the gpu


    # include <cmath> // This library enable the use of sqrt.
    # include <iostream>
   
    using namespace std;
   
    void primenum(long double); // Prototype...
   
    int c = 0;
   
    int main(){
        long double x = 0;
        cout<<"\n This program will generate all prime numbers up to the"
        <<"\n number you have entered below...\n";
        cout<<"\n Please enter a number: ";
        cin>> x;
        cout<<"\n Here are all the prime numbers up to "<<x<<".\n";
        primenum(x); //function invocation...
        cout<<endl<<"\nThere are "<<c
        <<" prime numbers less than or equal to "<<x<<".\n\n";
        return 0;
    }
    // This function will determine the primenumbers up to num.
    void primenum(long double x){
    bool prime = true; // Calculates the square-root of 'x'
    int number2;
    number2 =(int) floor (sqrt (x));
    for (int i = 1; i <= x; i++){
        for ( int j = 2; j <= number2; j++){
            if ( i!=j && i % j == 0 ){
                prime = false;
                break;
            }
        }
        if (prime){
            cout <<" "<<i<<" ";
            c += 1;
        }
        prime = true;
    }
    getchar();
    }

Version of prime generator running on GPU


    # include <cmath> // This library enable the use of sqrt.
    # include <iostream>
    # include <cuda_runtime.h>
   
    using namespace std;
   
    void primenum(long double); // Prototype...
   
    int c = 0;
   
    int main(){
        long double x = 0;
        cout<<"\n This program will generate all prime numbers up to the"
        <<"\n number you have entered below...\n";
        cout<<"\n Please enter a number: ";
        cin>> x;
        cout<<"\n Here are all the prime numbers up to "<<x<<".\n";
        primenum(x); //function invocation...
        cout<<endl<<"\nThere are "<<c
        <<" prime numbers less than or equal to "<<x<<".\n\n";
        return 0;
    }
   
    // This function will determine the primenumbers up to num.
    void primenum(long double x){
        //Array to hold generated primes on host
        int *primes_h = new int[x];
        //Device array to hold the primes on the device
        int *primes_d = new int[x];
        //allocate device memory and initialize device memory
        cudaMalloc((void**)&primes_d, x * sizeof(int));
        cudaMemset(&primes_d,sizeof(int),x * sizeof(int);
       
        //Kernal goes here
        //error checking
       
        //copy the array holding primes from device to host
        cudaMemcpy(primes_h, primes_d, x * sizeof(int), cudaMemcpyDeviceToHost);
       
        //display the primes
        for(int i=0; i<x ; i++){
            cout<<primes_h[i]<<endl;
        }
       
        //free allocated memory
        delete [] primes_h;
        cudaFree(primes_d);
       
        getchar();
    }

Almost Final version

# include <cmath> // This library enable the use of sqrt.

    # include <iostream>

	# include <ctime>

	#include<iomanip>

	#include<cstdlib>

    # include <cuda_runtime.h>

	//#include <times.h>

   

    using namespace std;

	

	inline clock_t getMilliSecs() {

		return clock() / (CLOCKS_PER_SEC / 1000);

	}



	__global__ void primegen(bool prime, int number2,int x,int *primes_d)

	{

      int c = 0;



	for (int i = 1; i <= x; i++)

	{

        for ( int j = 2; j <= number2; j++)

		{

            if ( i!=j && i % j == 0 )

			{

                prime = false;

                break;

            }

        }

        if (prime)

		{

           primes_d[c]=i;

            c += 1;

        }

        prime = true;

    }

	

	}	

   

    void primenum(long double); // Prototype...

   

 

   

    int main()

	{

        long double x = 0;

        cout<<"\n This program will generate all prime numbers up to the"<<"\n number you have entered below...\n";

        cout<<"\n Please enter a number: ";

        cin>> x;

        cout<<"\n Here are all the prime numbers up to "<<x<<".\n";

        primenum(x); //function invocation...

        //cout<<endl<<"\nThere are "<<c

        //<<" prime numbers less than or equal to "<<x<<".\n\n";

        return 0;

    }

   

    // This function will determine the primenumbers up to num.

    void primenum(long double x)

	{

		bool prime = true;

		//struct tms start_time, stop_time;

		  int number2;

		  number2 =(int) floor (sqrt (x));

		  clock_t start = getMilliSecs();

        //Array to hold generated primes on host

        int *primes_h = new int[(int)x];

        //Device array to hold the primes on the device

        int *primes_d = new int[(int)x];

        //allocate device memory and initialize device memory

        cudaMalloc((void**)&primes_d, (int)x * sizeof(int));

		// cudaMalloc((void**)&c_d, sizeof(int));

        cudaMemset(&primes_d,0,x * sizeof(int));

        //error checking

        cudaError_t error ;

        //Kernal goes here

		 primegen<<<1,1>>>(prime,number2,(int)x,primes_d);

		

		// extract error code from the kernel's execution

         error = cudaGetLastError();

         if (error != cudaSuccess) {

                 cout << cudaGetErrorString(error) << endl;

         }

       

        //copy the array holding primes from device to host

        error =cudaMemcpy(primes_h, primes_d, ((int)x) * sizeof(int), cudaMemcpyDeviceToHost);

     

         if (error != cudaSuccess) {

                 cout << cudaGetErrorString(error) << endl;

         }

		// cudaMemcpy(c_h, c_d, sizeof(int), cudaMemcpyDeviceToHost);

        //display the primes

		for(int i=0; i<(int)x ; i++){

			if(primes_h[i]>=2 && primes_h[i]<=(int)x){

				cout<<primes_h[i]<<endl;

			}

        }

       cout << "Elapsed time: " << (getMilliSecs() - start) << "ms" << endl;

      // cout<< "time: "<< (stop_s-start_s)/double(CLOCKS_PER_SEC)<<endl;

        //free allocated memory

		

        delete [] primes_h;

        cudaFree(primes_d);

       

        getchar();

    }

Assignment 3

Cuda Version:First Attempt


# include <cmath> // This library enable the use of sqrt.

    # include <iostream>

	# include <ctime>

	#include<iomanip>

	#include<cstdlib>

    # include <cuda_runtime.h>

	//#include <times.h>

   

    using namespace std;

	

	inline clock_t getMilliSecs() {

		return clock() / (CLOCKS_PER_SEC / 1000);

	}



	__global__ void primegen(bool prime, int number2,int x,int *primes_d)

	{

      int c = 0;

	  int idx = blockIdx.x * blockDim.x + threadIdx.x;

	  

	  for ( int i=1; i <= x; i++)

		{

			if( i!= idx && i%idx == 0 )

			{

				prime = false;

				break;

			}

		

			if(prime)

			{

				primes_d[c]=i;

				c += 1;

			}

				prime = true;

		}

		

			

	 } 

	  



	/*for (int i = 1; i <= x; i++)

	{

        for ( int j = 2; j <= number2; j++)

		{

            if ( i!=j && i % j == 0 )

			{

                prime = false;

                break;

            }

        }

        if (prime)

		{

           primes_d[c]=i;

            c += 1;

        }

        prime = true;  

		

    } */

	



   

    void primenum(long double); // Prototype...

   

 

   

    int main()

	{

        long double x = 0;

        cout<<"\n This program will generate all prime numbers up to the"<<"\n number you have entered below...\n";

        cout<<"\n Please enter a number: ";

        cin>> x;

        cout<<"\n Here are all the prime numbers up to "<<x<<".\n";

        primenum(x); //function invocation...

        //cout<<endl<<"\nThere are "<<c

        //<<" prime numbers less than or equal to "<<x<<".\n\n";

        return 0;

    }

   

    // This function will determine the primenumbers up to num.

    void primenum(long double x)

	{

	int   n = x;

	  int   d;

		bool prime = true;

		//struct tms start_time, stop_time;

		  int number2;

		  number2 =(int) floor (sqrt (x));

		  clock_t start = getMilliSecs();

		  

		   cudaDeviceProp prop;

         cudaGetDevice(&d);

         cudaGetDeviceProperties(&prop, d);

         int nThreads = prop.maxThreadsDim[0];

         int n_max = nThreads * prop.maxGridSize[0];

         if ( n> n_max) {

                n = n_max;

                cout << "n reduced to " << n << endl;

         } 

		  

        //Array to hold generated primes on host

        int *primes_h = new int[(int)x];

		

        //Device array to hold the primes on the device

        int *primes_d = new int[(int)x];

		

        //allocate device memory and initialize device memory

        cudaMalloc((void**)&primes_d, (int)x * sizeof(int));

		

		// cudaMalloc((void**)&c_d, sizeof(int));

        cudaMemset(&primes_d,0,x * sizeof(int));

		

        //error checking

        cudaError_t error ;

		

        //Kernal goes here

		 primegen<<<(n + nThreads - 1) / nThreads, nThreads>>>(prime,number2,(int)x,primes_d);

		

		// extract error code from the kernel's execution

		

         error = cudaGetLastError();

         if (error != cudaSuccess) {

                 cout << cudaGetErrorString(error) << endl;

         }

       

        //copy the array holding primes from device to host

		

        error =cudaMemcpy(primes_h, primes_d, ((int)x) * sizeof(int), cudaMemcpyDeviceToHost);

     

         if (error != cudaSuccess) {

                 cout << cudaGetErrorString(error) << endl;

         }

		// cudaMemcpy(c_h, c_d, sizeof(int), cudaMemcpyDeviceToHost);

        //display the primes

		for(int i=0; i<(int)x ; i++){

			if(primes_h[i]>=2 && primes_h[i]<=(int)x){

				cout<<primes_h[i]<<endl;

			}

        }

       cout << "Elapsed time: " << (getMilliSecs() - start) << "ms" << endl;

      // cout<< "time: "<< (stop_s-start_s)/double(CLOCKS_PER_SEC)<<endl;

        //free allocated memory

		

        delete [] primes_h;

        cudaFree(primes_d);

       

        getchar();

    }

Conclusion: Logical Error

GpuA3error.png

The prime number generated seems to have run into some logical error. It does not generate the prime numbers correctly. Instead spits out all numbers.

Cuda Version: Attempt Two

Gives a run time error "invalid argument". Logical error still persists.

Final Cuda version

#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <ctime>
#include <cuda_runtime.h>

using namespace std;

/**
 * This macro checks return value of the CUDA runtime call and exits
 * the application if the call failed.
 */
#define CUDA_CHECK_RETURN(value) {                                            \
    cudaError_t _m_cudaStat = value;                                        \
    if (_m_cudaStat != cudaSuccess) {                                        \
        fprintf(stderr, "Error %s at line %d in file %s\n",                    \
                cudaGetErrorString(_m_cudaStat), __LINE__, __FILE__);        \
        exit(1);                                                            \
    } }

/**
 * Kernel code to generate and detect primes
 */
__global__ void prime(int *num, int blockNum, int threadNum, int size) {
    const int tid = blockIdx.x * blockDim.x + threadIdx.x;
    const int bid = blockIdx.y * blockDim.y + threadIdx.y;
    __syncthreads();

    /**
     * Generate prime numbers and store them in the array.
     * The first element is always 2
     */
    if(tid == 0) {
        num[tid] = 2;
    } else {
        num[tid] = 2 * tid + 1;
    }

    int tmp = bid * threadNum + tid;

    int step1 = 2 * tmp + 3;
    int step2 = tmp + 1;

    while(tmp < size) {
        int i = 1;
        /**
         * Check if an element is not prime, if it isn't set it to 0.
         */
        while((step1 * i + step2) < size) {
            num[step1 * i + step2] = 0;
            i++;
        }
        tmp += blockNum * threadNum;
        __syncthreads();
    }
}

int main(int argc, char* argv[]) {
    if(argc != 2) {
        cout << "Incorrect no of arguments" << endl;
        return 1;
    }
    int n = atoi(argv[1]);

    /**
     * variable declarations
     */
    int *device;
    int host[n];
    int d;
    cudaDeviceProp prop;

    /**
     * Get the properties of the device in use
     */
    cudaGetDevice(&d);
    cudaGetDeviceProperties(&prop, d);
    int numberOfBlocks = 8;
    int maxThreadsPerBlock = prop.maxThreadsPerBlock;
    int numberOfThreads = maxThreadsPerBlock/numberOfBlocks;

    /**
     * Start timer
     */
    clock_t cb, ce;
    cb = clock();

    /**
     * Allocate memory on the device
     */
    CUDA_CHECK_RETURN(cudaMalloc((void**) &device, sizeof(int) * n));

    /**
     * Call kernel with appropriate grid and thread size
     */
    prime<<<numberOfBlocks, numberOfThreads>>>(device, numberOfBlocks, numberOfThreads, n);

    /**
     * Copy results back to host
     */
    CUDA_CHECK_RETURN(cudaMemcpy(&host, device, sizeof(int) * n, cudaMemcpyDeviceToHost));

    /**
     * Free memory on device
     */
    CUDA_CHECK_RETURN(cudaFree(device));

    /**
     * Output values
     */
    for (int i = 0; i < n; i++)
        if (host[i] != 0)
            cout << host[i] << endl;

    /**
     * Stop timer
     */
    ce = clock();
    cout << "Prime generation - took " << double(ce - cb)/CLOCKS_PER_SEC << " seconds" << endl;
}
Manual Delete Warning
Final version's errors, warnings and observations
  • If a number over 515 is entered as the launch argument, the program will display random values at the end of the list of prime numbers
  • When attempting to delete the host array manually in the program, a warning is displayed
Manual Delete Crash
  • The program crashes at the end if the host array is manually deleted
Successful run of Prime generation

PrimeSuccessfulRun.png