In "Advanced Programming in the UNIX Environment", W. Richard Stevens says it is a performance optimization:
By specifying the highest descriptor we're interested in, the kernel can avoid going through hundred of unused bits in the three descriptor sets, looking for bits that are turned on.
(1st edition, page 399)
If you are doing any kind of UNIX systems programming, the APUE book is highly recommended.
UPDATE
An fd_set is usually able to track up to 1024 file descriptors.
The most efficient way to track which fds are set to 0 and which are set to 1 would be a bitset, so each fd_set would consist of 1024 bits.
On a 32-bit system, a long int (or "word") is 32 bits, so that means each fd_set is
1024 / 32 = 32 words.
If nfds is something small, such as 8 or 16, which it would be in many applications, it only needs to look inside the 1st word, which should clearly be faster than looking inside all 32.
(See FD_SETSIZE and __NFDBITS from /usr/include/sys/select.h for the values on your platform.)
UPDATE 2
As to why the function signature isn't
int select(fd_set *readfds, int nreadfds,
fd_set *writefds, int nwritefds,
fd_set *exceptfds, int nexceptfds,
struct timeval *timeout);
My guess is it's because the code tries to keep all the arguments in registers, so the CPU can work on them faster, and if it had to track an extra 2 variables, the CPU might not have enough registers.
So in other words, select is exposing an implementation detail so that it can be faster.