Safety, usability, efficiency

next - skip - up - start

Some general comments

A library like newmat needs to balance safety, usability and efficiency.

By safety, I mean getting the right answer, and not causing crashes or damage to the computer system.

By usability, I mean being easy to learn and use, including not being too complicated, being intuitive, saving the users' time, being nice to use.

Efficiency means minimising the use of computer memory and time.

In the early days of computers the emphasis was on efficiency. But computer power gets cheaper and cheaper, halving in price every 18 months. On the other hand the unaided human brain is probably not a lot better than it was 100,000 years ago! So we should expect the balance to shift to put more emphasis on safety and usability and a little less on efficiency. So I don't mind if my programs are a little less efficient than programs written in pure C (or Fortran) if I gain substantially in safety and usability. But I would mind if they were a lot less efficient.

Type of use

Second reason for putting extra emphasis on safety and usability is the way I and, I suspect, most other users actually use newmat. Most completed programs are used only a few times. Some result is required for a client, paper or thesis. The program is developed and tested, the result is obtained, and the program archived. Of course bits of the program will be recycled for the next project. But it may be less usual for the same program to be run over and over again. So the cost, computer time + people time, is in the development time and often, much less in the actual time to run the final program. So good use of people time, especially during development is really important. This means you need highly usable libraries.

So if you are dealing with matrices, you want the good interface that I have tried to provide in newmat, and, of course, reliable methods underneath it.

Of course, efficiency is still important. We often want to run the biggest problem our computer will handle and often a little bigger. The C++ language almost lets us have both worlds. We can define a reasonably good interface, and get good efficiency in the use of the computer.

Levels of access

We can imagine the black box model of a newmat. Suppose the inside is hidden but can be accessed by the methods described in the reference section. Then the interface is reasonably consistent and intuitive. Matrices can be accessed and manipulated in much the same way as doubles or ints in regular C. All accesses are checked. It is most unlikely that an incorrect index will crash the system. In general, users do not need to use pointers, so one shouldn't get pointers pointing into space. And, hopefully, you will get simpler code and so less errors.

There are some exceptions to this. In particular, the C-like subscripts are not checked for validity. They give faster access but with a lower level of safety.

Then there is the Store() function which takes you to the data array within a matrix. This takes you right inside the black box. But this is what you have to use if you are writing, for example, a new matrix factorisation, and require fast access to the data array. I have tried to write code to simplify access to the interior of a rectangular matrix, see file newmatrm.cpp, but I don't regard this as very successful, as yet, and have not included it in the documentation. Ideally we should have improved versions of this code for each of the major types of matrix. But, in reality, most of my matrix factorisations are written in what is basically the C language with very little C++.

So our box is not very black. You have a choice of how far you penetrate. On the outside you have a good level of safety, but in some cases efficiency is compromised a little. If you penetrate inside the box safety is reduced but you can get better efficiency.

Some performance data

This section looks at the performance on newmat for simple sums, comparing it with pure C code and with a somewhat unintelligent array program.

The following table lists the time (in seconds) for carrying out the operations X=A+B;, X=A+B+C;, X=A+B+C+D;, where X,A,B,C,D are of type ColumnVector, with a variety of programs. I am using Borland C++, version 5 in 32 bit console mode under windows NT 4.0 on a PC with a 150 mhz pentium and 128 mbytes of memory.

        length	iters.	newmat	subs.	C	C-resz	array

    X=A+B
        2000000	2	1.2	3.7	1.2	1.4	3.3
        200000	20	1.2	3.7	1.2	1.5	3.1
        20000	200	1.0	3.6	1.0	1.2	2.9
        2000	2000	1.0	3.6	0.9	0.9	2.2
        200	20000	0.8	3.0	0.4	0.5	1.9
        20	200000	5.5	2.9	0.4	0.9	2.8
        2	2000000	43.9	3.2	1.0	4.2	12.3

    X=A+B+C						
        2000000	2	2.5	4.6	1.6	2.1	32.5
        200000	20	2.1	4.6	1.6	1.8	6.2
        20000	200	1.8	4.5	1.5	1.8	5.6
        2000	2000	1.8	4.4	1.3	1.3	3.9
        200	20000	2.2	4.3	1.0	0.9	2.3
        20	200000	8.5	4.3	1.0	1.2	3.0
        2	2000000	62.5	3.9	1.0	4.4	17.7

    X=A+B+C+D						
        2000000	2	3.7	6.7	2.4	2.8	260.7
        200000	20	3.7	6.7	2.4	2.5	9.2
        20000	200	3.4	6.6	2.3	2.9	8.2
        2000	2000	2.9	6.4	2.0	2.0	5.9
        200	20000	2.5	5.5	1.0	1.3	4.3
        20	200000	9.9	5.5	1.0	1.6	4.5
        2	2000000	76.5	5.8	1.7	5.0	24.9
The first column gives the lengths of the arrays, the second the number of iterations and the remaining columns the total time required in seconds. If the only thing that consumed time was the double precision addition then the numbers within each block of the table would be the same.

The column labelled newmat is using the standard newmat add. In the next column the calculation is using the usual C style for loop and accessing the elements using newmat subscripts such as A(i). The column labelled C uses the usual C method: while (j--) *x++ = *a++ + *b++; . The following column also includes an X.ReSize() in the outer loop to correspond to the reassignment of memory that newmat would do. The final column is the time taken by a simple array package that makes no attempt to eliminate unnecessary copying or to recycle temporary memory but does have array definitions of the basic operators. It does, however, do its sums in blocks of 4 and copies in blocks of 8 in the same way that newmat does.

Here are my conclusions.

In summary: for the situation considered here, newmat is doing very well for large ColumnVectors, even for sums with several terms, but not so well for shorter ColumnVectors.

next - skip - up - start