Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add two-qubit lambda in qubitvector #133

Merged
merged 12 commits into from
Apr 15, 2019
Merged

Conversation

hhorii
Copy link
Collaborator

@hhorii hhorii commented Apr 6, 2019

Summary

This PR optimizes two-qubit gate operations in qubitvector

Details and comments

Currently two-qubit operations use index. An index is generated for each iteration in a loop.

This PR introduces a new apply_lambda for two-qubits operations. cnot is implemented as follows:

  const int_t GAP_ctrl = BITS[qubit_ctrl];
  const int_t GAP_trgt = BITS[qubit_trgt];
  auto lambda = [&](const int_t i00)->void {
    auto i10 = i00 | GAP_ctrl;
    std::swap(data_[i10], data_[i10 | GAP_trgt]);
  };
  apply_lambda(lambda, qubit_ctrl, qubit_trgt);

In the above, i01 = i00 | GAP_trgt and i11 = i 10 | GAP_trgt. This PR may increases arithmetic operations, but they are cheap comparing with index generation.

My local environment (MacBook Pro (Retina, 13-inch, Early 2015)), cnot x 25 for a 25-qubits circuit took 3.19 sec with this optimization and 9.55 sec without this optimization.

@chriseclectic
Copy link
Member

@hhorii PR #124 removes these two qubit gates and replaces them with general multi-controlled versions.

If performance is a lot better can you start from that PR and look at adding this back in as special case for N=2 qubit gates.

@hhorii
Copy link
Collaborator Author

hhorii commented Apr 11, 2019

Static index with std::array can show the similar performance. This latest version add static index on top of #124.

@chriseclectic
Copy link
Member

chriseclectic commented Apr 12, 2019

EDIT: I just realised i was running the stabilizer simulator, not statevector doh, now i see a big difference. I think PR where we removed static indexing earlier was flawed.

Test case

Using a single-shot test circuit of N CNOTS for N qubits (N=10,15,20,25)

from qiskit import *
sim = Aer.get_backend('qasm_simulator')
opts = {'method': 'statevector'}

def make_qobj(nq):
    q = QuantumRegister(nq)
    qc = QuantumCircuit(q)
    for j in range(nq):
        qc.cx(q[j], q[(j + 1) % nq])
    return compile(qc, Aer.get_backend('qasm_simulator'), shots=1)

nqs = [10, 15, 20, 25]
qobjs = [make_qobj(nq) for nq in nqs]

and simple timing using Jupyter

%%timeit
result = sim.run(qobj, validate=False, backend_options=opts).result()

EDIT: UPDATED
I get results on my laptop of

Using dynamic indexes:

  • N=10: 16.2 ms ± 2.65 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
  • N=15: 38.6 ms ± 6.95 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
  • N=20: 435 ms ± 43.3 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
  • N=25: 11.5 s ± 404 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

Using static indexes:

  • N=10: 14 ms ± 554 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
  • N=15: 30.2 ms ± 6.03 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
  • N=20: 99.4 ms ± 11.3 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
  • N=25: 1.51 s ± 155 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

@chriseclectic
Copy link
Member

Some further testing and I think we can remove the single-qubit apply matrix functions and use the old static indexing. Changing the above example to apply and x gate instead of cx and comparing the current 1-qubit apply_lambda to an N=1 static indexed case I get that they are about the same (or that static indexing is slightly faster).

@chriseclectic chriseclectic merged commit edee8a6 into Qiskit:master Apr 15, 2019
gadial pushed a commit to gadial/qiskit-aer that referenced this pull request Apr 16, 2019
* add two qubit lambda for cnot

* use two qubit lambda for swap and cz

* use lambda with indexes for single-qubit operation
dcmckayibm pushed a commit to dcmckayibm/qiskit-aer that referenced this pull request Nov 3, 2019
* add two qubit lambda for cnot

* use two qubit lambda for swap and cz

* use lambda with indexes for single-qubit operation
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants