Thursday, March 30, 2006

Killer: test 1 (passed)

This is the first test to understand what makes my MacIntel GUI terribly slow when some software run.

I wrote a small C++ program on that purpose. It makes some operations on matrices, but it does them in a quite inefficient way. When we multiply two matrices, it creates two vector objects, allocates memory for them, multiplies them, stores the result, and destroys them.

Of course this is not what you would be doing when implementing a matrix library, but we are trying to understand which software bugs are more problematic on the MacIntel and aren't on the PPC (in my previous post I told running some buggy sw on the Powerbook wasn't an issue, but made the MacIntel almost unusable).

This software does a lot of computations (it multiplies two quite large matrices of "points" -- structures of three doubles). Points use vectorial product. It does a lot of allocation and deallocation of small area of memory and I added I/O making it log the result each time it multiplies two points (that is a lot of I/O, since when we multiply two 500 element matrices it makes 500*500*500 point multiplications).

The verdict is positive. It is running right now (it hasn't yet finished) but the computer is perfectly usable.

Now I'm going to write a software that allocates and deallocates large areas of memory and then one that leaks a lot of memory. I do think, memory leaks are the cause of the "GUI slowness". However I still don't understand why the powerbook (that has 1/3 the RAM my iMac has) had no troubles.

Here I post the source of this simple software. Keep in mind that this was designed to be inefficient (don't use it, it sucks).

#include <cstdlib>
#include <iostream>
#include <ostream>
#include <fstream>

std::ofstream LOG;

struct Point{
        double x;
        double y;
        double z;
        Point() :
                x(0.0),
                y(0.0),
                z(0.0) {}
        Point(double l_x, double l_y, double l_z) :
                x(l_x),
                y(l_y),
                z(l_z) {}
        static Point random(){
                Point p(
                    rand()/(double)RAND_MAX,
                    rand()/(double)RAND_MAX,
                    rand()/(double)RAND_MAX
                );
                return p;
        }
};

std::ostream& operator<<(std::ostream& out, const Point& p){
    out << "(" << p.x << "," << p.y << "," << p.z << ")" ;
    return out;
}

Point operator*(const Point& op1, const Point& op2){
        Point res(
            op1.y * op2.z - op1.z * op2.y,
            op1.z * op2.x - op1.x * op2.z,
            op1.x * op2.y - op1.y * op2.x
        );
        LOG << res << std::endl;
        return res;
}

Point operator+(const Point& op1, const Point& op2){
        Point res(
            op1.x + op2.x,
            op1.y + op2.y,
            op1.z + op2.z
        );
        return res;
}

template<typename T, size_t size>
class Vector{
public:
        Vector(){
                mem_ = new T[size];
        }
        
        Vector(const Vector<T, size>& o){
            mem_ = new T[size];
            for(size_t i=0; i<size; ++i){
                mem_[i]=o.mem_[i];
            }
        }
        
        ~Vector(){
                delete [] mem_;
        }
        
        T& operator[](size_t i){
                return mem_[i];
        }
        
        const T& operator[](size_t i) const{
                return mem_[i];
        }
private:
        T* mem_;
    Vector<T, size>& operator=(const Vector<T, size>&);
};

template<typename T, size_t size>
T operator*(const Vector<T, size>& op1, const Vector<T, size> &op2){
        T acc;
        for(size_t i=0; i<size; ++i){
                acc = acc + op1[i]*op2[i];
        }
        return acc;
}

template<typename T, size_t size>
class Matrix{
public:
        Matrix(){
                mem_ = new T[size*size];
                for(size_t i=0; i<size; ++i){
                        for(size_t j=0; j<size; ++j){
                                get(i,j)=T::random();
                        }
                }
        }
        Matrix(const Matrix<T, size>& o){
                mem_ = new T[size*size];
                for(size_t i=0; i<size*size; ++i){
                    mem_[i] = o.mem_[i];
                }
        }
        ~Matrix(){
                delete [] mem_;
        }
Matrix<T, size>& operator=(const Matrix<T, size>& o){               
                for(size_t i=0; i<size*size; ++i){
mem_[i] = o.mem_[i];
                }
return (*this);
}
        T& get(size_t i, size_t j){
                return mem_[j*size + i];
        }
        
        const T& get(size_t i, size_t j) const{
                return mem_[j*size + i];
        }
        
        Vector<T, size> col(size_t j) const{
                Vector<T, size> v;
                for(size_t i=0; i<size; ++i){
                        v[i] = get(i,j);
                }
                return v;
        }
        
        Vector<T, size> row(size_t i) const{
                Vector<T, size> v;
                for(size_t j=0; j<size; ++j){
                        v[j] = get(i,j);
                }
                return v;
        }
private:
        T* mem_;
};

template<typename T, size_t size>
Matrix<T, size> operator*(Matrix<T, size>& op1, 
                                                  Matrix<T, size>& op2)
{
        Matrix<T, size> res;
        for(size_t i=0; i<size; ++i){
                for(size_t j=0; j<size; ++j){
                        res.get(i,j) = op1.row(i) * op2.col(j);
                }
        }
        return res;
}
int main(){
        const size_t SIZE = 500;
LOG.open("log.txt");
        Matrix<Point, SIZE> m1;
        Matrix<Point, SIZE> m2;
        Matrix<Point, SIZE> res;
res= m1*m2;
LOG.close();
}

No comments: