In the bash shell, subshells are implemented by forking a child process, so you won't see a case of a subshell not running in a child process in that shell.
ksh93 is the only shell that I know that skips the forking when possible for subshells (an optimisation that is still quite buggy and that the successive people that have tried to maintain it after AT&T disbanded the team that had written it have considered removing).
If you do for instance:
 strace ksh93 -c 'pwd; (cd /; umask 0; pwd; exit 2); pwd'
You'll see ksh93 not forking any process but do something like this instead:
openat(AT_FDCWD, ".", O_RDONLY|O_PATH)  = 3
fcntl(3, F_DUPFD, 10)                   = 10
close(3)                                = 0
fcntl(10, F_SETFD, FD_CLOEXEC)          = 0
[...]
Which saves the current directory on fd 10. Then:
chdir("/")                              = 0
umask(000)                              = 002
Which changes the current directory and umask in the subshell. And upon termination of the subshell (the exit 2 not calling the _exit() system call):
fchdir(10)                              = 0
close(10)                               = 0
To restore the current working directory and:
umask(002)                              = 000
To restore the umask.
Some shells like FreeBSD's sh can skip the fork in very specific cases, like in:
var=$(printf %04d "$n")
(here with a printf builtin, and no change to the environment is being done in there).
In a pipeline, all components have to run concurrently, so they have to run in separate processes, even in ksh93.
In bash, they all run in child processes. In AT&T ksh or zsh, or with bash -O lastpipe (when non-interactive), the rightmost one doesn't (of course, you still need to fork a child process to run external commands such as ps).
You don't see an extra bash process in ps >&2 | ps or (ps) because ps is executed directly  in that child process, which before executing ps was bash interpreting the pipeline component: the subshell. For instance, in:
n=0; /bin/true "$((n=1))" | /bin/echo "$((n=2))"; echo "$n"
You'll see 2 and 0 in bash, and 2 and 2 in zsh/ksh93. /bin/true and /bin/echo are executed in child processes, /bin/true directly in the subshell process that had done n=1 earlier, same in bash for /bin/echo (and n=2), but in zsh/ksh/bash -O lastpipe, the n=2 was done in the main shell process, and a child only forked to execute that external utility, just like when you run /bin/echo "$((n=2))" not as part of a pipeline.
In bash (contrary to zsh/ksh), you do see an extra bash process in (: anything; ps), the optimisation is only done if the subshell has only one external command, you'd need to use exec to do that optimisation by hand there: (: anything; exec ps).
Same goes for { ps; } | cat.
     
    
a=3; (a=12); echo $a. The reverse is also true: at least on Linux, one could implement multiple processes within a single subshell environment (i.e.cdcould be an external command, running in a separate process, and still change the cwd of its parent). But AFAIK no mainstream shell is making use of that.