pre_get_posts : ‘post__not_in’ doesn’t work with global variable

You have to declare $popular to be global before you use it. Based on the code you’ve posted you haven’t done that.

global $popular;
$popular[] = 1 //post id=1
$popular[] = 2 //post id=2
$popular[] = 3 //post id=3

However, if you mean the index.php in the theme, that file is not always used. You may be defining the variable in a file that does not load when you need it to. It is hard to tell whether this is the case due to the limited code you posted.

pre_get_posts is going to run before any of the theme files anyway, except, if functions.php (or any files included from there). You can echo values out from that filter and from header.php to prove that to yourself.

Also, there may be a better way to do this than to declare a global variable. Again, due to the limited code it is hard to say.

Overall, it sounds like you need to rethink how you are going to accomplish this. A much better description of what you are trying to accomplish would help.

Reference

http://php.net/manual/en/language.variables.scope.php