If you haven't already, look into using optimisation algorithms and data structures such as quadtrees, spatial hashing, binary space partitioning, and so on.
A quadtree in particular would do just fine in this case, and is fairly simple to implement. It subdivides a rectangular area of the game world into four equally sized rectangles, and continues to do so for each of the resulting rectangles for a specified number of levels. If an object overlaps one of these rectangles, its reference is stored in that rectangle's 'bucket' (array of object references).
When you look for a particular object inside the quadtree, you check each rectangle's bucket for the object, and continue down to the last rectangle (the leaf of the quadtree) that contains the object in its bucket. Then you just perform a check on each of the object in that bucket to find the one you're looking for.
In your case, you would look for the rectangles the ray intersects, and then sort through the objects to see which is the closest one. That part could be a little tricky, but it shouldn't be impossible to do.
If you have rooms or walls / barriers, you could look into partitioning the map according to how the walls intersect when extended infinitely. Objects in the same room or region would be visible to each other, which limits the pool of objects you have to check the ray against.