It could be any number of things.
The disks on the server may not be setup correctly. The additional load on the server by other users could easily slow down your query. If the indexes are different then the query will run at a very different speed. Did you check the execution plans between the two machines?
Are the two machines at the same patch level? When were the indexes and statistics last updated?
It could be that the 16 core machine had enough cores available that SQL tried to run the query in multiple threads, and it’s a query which performs better as a single thread. You could have blocking issues on the production machine which are stopping your query.
Without more machine, database and query information it’ll be hard to nail it down to a single cause.
A few things you can try off the top are:
Rebuild indexes and update statistics
Run the query as a single thread by using the MAXDOP=1 option
Try running the query with the NOLOCK hint to prevent locking. This will give you dirty reads, but will stop the query from being blocked while others are writing to the table(s).
FROM Table WITH (NOLOCK)</pre>