Skip to content

Commit

Permalink
Improved randomness sources in parallel ops.
Browse files Browse the repository at this point in the history
  • Loading branch information
MichaelBroughton committed Apr 6, 2021
1 parent 3980ee6 commit 29a986d
Show file tree
Hide file tree
Showing 7 changed files with 119 additions and 63 deletions.
37 changes: 22 additions & 15 deletions tensorflow_quantum/core/ops/noise/tfq_noisy_expectation.cc
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ limitations under the License.
==============================================================================*/

#include <memory>
#include <random>
#include <vector>

#include "../qsim/lib/channel.h"
Expand Down Expand Up @@ -169,6 +170,13 @@ class TfqNoisyExpectationOp : public tensorflow::OpKernel {
auto sv = ss.Create(largest_nq);
auto scratch = ss.Create(largest_nq);

unsigned long r_seed =
std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::system_clock::now().time_since_epoch())
.count();
std::mt19937 gen(r_seed);
std::uniform_int_distribution<> distrib(1, 1 << 30);

// Simulate programs one by one. Parallelizing over state vectors
// we no longer parallelize over circuits. Each time we encounter a
// a larger circuit we will grow the Statevector as necessary.
Expand Down Expand Up @@ -199,13 +207,9 @@ class TfqNoisyExpectationOp : public tensorflow::OpKernel {

while (1) {
ss.SetStateZero(sv);
// time since epoch seeds random generator.
unsigned long r_seed =
std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::system_clock::now().time_since_epoch())
.count();
QTSimulator::RunOnce(param, ncircuits[i], r_seed, ss, sim, scratch, sv,
unused_stats);

QTSimulator::RunOnce(param, ncircuits[i], distrib(gen), ss, sim,
scratch, sv, unused_stats);

// Use this trajectory as a source for all expectation calculations.
for (int j = 0; j < pauli_sums[i].size(); j++) {
Expand Down Expand Up @@ -266,6 +270,11 @@ class TfqNoisyExpectationOp : public tensorflow::OpKernel {

output_tensor->setZero();

unsigned long r_seed =
std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::system_clock::now().time_since_epoch())
.count();

Status compute_status = Status::OK();
auto c_lock = tensorflow::mutex();
auto DoWork = [&](int start, int end) {
Expand All @@ -277,6 +286,9 @@ class TfqNoisyExpectationOp : public tensorflow::OpKernel {
auto sv = ss.Create(largest_nq);
auto scratch = ss.Create(largest_nq);

std::mt19937 gen(r_seed + start);
std::uniform_int_distribution<> distrib(1, 1 << 30);

for (int i = 0; i < ncircuits.size(); i++) {
int nq = num_qubits[i];
int rep_offset = rep_offsets[start][i];
Expand Down Expand Up @@ -305,14 +317,9 @@ class TfqNoisyExpectationOp : public tensorflow::OpKernel {

while (1) {
ss.SetStateZero(sv);
// time since epoch seeds random generator.
unsigned long r_seed =
std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::system_clock::now().time_since_epoch())
.count();

QTSimulator::RunOnce(param, ncircuits[i], r_seed, ss, sim, scratch,
sv, unused_stats);

QTSimulator::RunOnce(param, ncircuits[i], distrib(gen), ss, sim,
scratch, sv, unused_stats);

// Compute expectations across all ops using this trajectory.
for (int j = 0; j < pauli_sums[i].size(); j++) {
Expand Down
45 changes: 27 additions & 18 deletions tensorflow_quantum/core/ops/noise/tfq_noisy_sampled_expectation.cc
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ limitations under the License.
==============================================================================*/

#include <memory>
#include <random>
#include <vector>

#include "../qsim/lib/channel.h"
Expand Down Expand Up @@ -170,6 +171,14 @@ class TfqNoisySampledExpectationOp : public tensorflow::OpKernel {
auto sv = ss.Create(largest_nq);
auto scratch = ss.Create(largest_nq);

// time since epoch seeds random generator.
unsigned long r_seed =
std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::system_clock::now().time_since_epoch())
.count();
std::mt19937 gen(r_seed);
std::uniform_int_distribution<> distrib(1, 1 << 30);

// Simulate programs one by one. Parallelizing over state vectors
// we no longer parallelize over circuits. Each time we encounter a
// a larger circuit we will grow the Statevector as necessary.
Expand Down Expand Up @@ -200,23 +209,19 @@ class TfqNoisySampledExpectationOp : public tensorflow::OpKernel {

while (1) {
ss.SetStateZero(sv);
// time since epoch seeds random generator.
unsigned long r_seed =
std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::system_clock::now().time_since_epoch())
.count();
QTSimulator::RunOnce(param, ncircuits[i], r_seed, ss, sim, scratch, sv,
unused_stats);

QTSimulator::RunOnce(param, ncircuits[i], distrib(gen), ss, sim,
scratch, sv, unused_stats);

// Use this trajectory as a source for all expectation calculations.
for (int j = 0; j < pauli_sums[i].size(); j++) {
if (run_samples[j] >= num_samples[i][j]) {
continue;
}
float exp_v = 0.0;
OP_REQUIRES_OK(
context, ComputeSampledExpectationQsim(pauli_sums[i][j], sim, ss,
sv, scratch, 1, &exp_v));
OP_REQUIRES_OK(context, ComputeSampledExpectationQsim(
pauli_sums[i][j], sim, ss, sv, scratch, 1,
gen, &exp_v));
rolling_sums[j] += static_cast<double>(exp_v);
run_samples[j]++;
}
Expand Down Expand Up @@ -267,6 +272,11 @@ class TfqNoisySampledExpectationOp : public tensorflow::OpKernel {

output_tensor->setZero();

unsigned long r_seed =
std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::system_clock::now().time_since_epoch())
.count();

Status compute_status = Status::OK();
auto c_lock = tensorflow::mutex();
auto DoWork = [&](int start, int end) {
Expand All @@ -278,6 +288,10 @@ class TfqNoisySampledExpectationOp : public tensorflow::OpKernel {
auto sv = ss.Create(largest_nq);
auto scratch = ss.Create(largest_nq);

// time since epoch seeds random generator.
std::mt19937 gen(r_seed + start);
std::uniform_int_distribution<> distrib(1, 1 << 30);

for (int i = 0; i < ncircuits.size(); i++) {
int nq = num_qubits[i];
int rep_offset = rep_offsets[start][i];
Expand Down Expand Up @@ -306,14 +320,9 @@ class TfqNoisySampledExpectationOp : public tensorflow::OpKernel {

while (1) {
ss.SetStateZero(sv);
// time since epoch seeds random generator.
unsigned long r_seed =
std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::system_clock::now().time_since_epoch())
.count();

QTSimulator::RunOnce(param, ncircuits[i], r_seed, ss, sim, scratch,
sv, unused_stats);
QTSimulator::RunOnce(param, ncircuits[i], distrib(gen), ss, sim,
scratch, sv, unused_stats);

// Compute expectations across all ops using this trajectory.
for (int j = 0; j < pauli_sums[i].size(); j++) {
Expand All @@ -325,7 +334,7 @@ class TfqNoisySampledExpectationOp : public tensorflow::OpKernel {
NESTED_FN_STATUS_SYNC(
compute_status,
ComputeSampledExpectationQsim(pauli_sums[i][j], sim, ss, sv,
scratch, 1, &exp_v),
scratch, 1, gen, &exp_v),
c_lock);
rolling_sums[j] += static_cast<double>(exp_v);
run_samples[j]++;
Expand Down
37 changes: 21 additions & 16 deletions tensorflow_quantum/core/ops/noise/tfq_noisy_samples.cc
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ limitations under the License.

#include <stdlib.h>

#include <random>
#include <string>

#include "../qsim/lib/channel.h"
Expand Down Expand Up @@ -148,6 +149,13 @@ class TfqNoisySamplesOp : public tensorflow::OpKernel {
auto sv = ss.Create(largest_nq);
auto scratch = ss.Create(largest_nq);

unsigned long r_seed =
std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::system_clock::now().time_since_epoch())
.count();
std::mt19937 gen(r_seed);
std::uniform_int_distribution<> distrib(1, 1 << 30);

// Simulate programs one by one. Parallelizing over state vectors
// we no longer parallelize over circuits. Each time we encounter a
// a larger circuit we will grow the Statevector as nescessary.
Expand All @@ -171,14 +179,9 @@ class TfqNoisySamplesOp : public tensorflow::OpKernel {

for (int j = 0; j < num_samples; j++) {
ss.SetStateZero(sv);
// time since epoch seeds random generator.
unsigned long r_seed =
std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::system_clock::now().time_since_epoch())
.count();

QTSimulator::RunOnce(param, ncircuits[i], r_seed, ss, sim, scratch, sv,
gathered_samples);

QTSimulator::RunOnce(param, ncircuits[i], distrib(gen), ss, sim,
scratch, sv, gathered_samples);
uint64_t q_ind = 0;
uint64_t mask = 1;
bool val = 0;
Expand Down Expand Up @@ -233,6 +236,11 @@ class TfqNoisySamplesOp : public tensorflow::OpKernel {
}
}

unsigned long r_seed =
std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::system_clock::now().time_since_epoch())
.count();

auto DoWork = [&](int start, int end) {
// Begin simulation.
const auto tfq_for = qsim::SequentialFor(1);
Expand All @@ -242,6 +250,9 @@ class TfqNoisySamplesOp : public tensorflow::OpKernel {
auto sv = ss.Create(largest_nq);
auto scratch = ss.Create(largest_nq);

std::mt19937 gen(r_seed + start);
std::uniform_int_distribution<> distrib(1, 1 << 30);

for (int i = 0; i < ncircuits.size(); i++) {
int nq = num_qubits[i];
int j = start > 0 ? offset_prefix_sum[start - 1][i] : 0;
Expand All @@ -263,14 +274,8 @@ class TfqNoisySamplesOp : public tensorflow::OpKernel {

while (1) {
ss.SetStateZero(sv);
// time since epoch seeds random generator.
unsigned long r_seed =
std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::system_clock::now().time_since_epoch())
.count();

QTSimulator::RunOnce(param, ncircuits[i], r_seed, ss, sim, scratch,
sv, gathered_samples);
QTSimulator::RunOnce(param, ncircuits[i], distrib(gen), ss, sim,
scratch, sv, gathered_samples);

uint64_t q_ind = 0;
uint64_t mask = 1;
Expand Down
19 changes: 17 additions & 2 deletions tensorflow_quantum/core/ops/tfq_simulate_sampled_expectation_op.cc
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ limitations under the License.
==============================================================================*/

#include <memory>
#include <random>
#include <vector>

#include "../qsim/lib/circuit.h"
Expand Down Expand Up @@ -157,6 +158,12 @@ class TfqSimulateSampledExpectationOp : public tensorflow::OpKernel {
auto sv = ss.Create(largest_nq);
auto scratch = ss.Create(largest_nq);

unsigned long r_seed =
std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::system_clock::now().time_since_epoch())
.count();
std::mt19937 gen(r_seed);

// Simulate programs one by one. Parallelizing over state vectors
// we no longer parallelize over circuits. Each time we encounter a
// a larger circuit we will grow the Statevector as necessary.
Expand Down Expand Up @@ -185,7 +192,7 @@ class TfqSimulateSampledExpectationOp : public tensorflow::OpKernel {
float exp_v = 0.0;
OP_REQUIRES_OK(context, ComputeSampledExpectationQsim(
pauli_sums[i][j], sim, ss, sv, scratch,
num_samples[i][j], &exp_v));
num_samples[i][j], gen, &exp_v));
(*output_tensor)(i, j) = exp_v;
}
}
Expand All @@ -204,6 +211,11 @@ class TfqSimulateSampledExpectationOp : public tensorflow::OpKernel {

const int output_dim_op_size = output_tensor->dimension(1);

unsigned long r_seed =
std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::system_clock::now().time_since_epoch())
.count();

Status compute_status = Status::OK();
auto c_lock = tensorflow::mutex();
auto DoWork = [&](int start, int end) {
Expand All @@ -216,6 +228,9 @@ class TfqSimulateSampledExpectationOp : public tensorflow::OpKernel {
StateSpace ss = StateSpace(tfq_for);
auto sv = ss.Create(largest_nq);
auto scratch = ss.Create(largest_nq);

std::mt19937 gen(r_seed + start);

for (int i = start; i < end; i++) {
cur_batch_index = i / output_dim_op_size;
cur_op_index = i % output_dim_op_size;
Expand Down Expand Up @@ -249,7 +264,7 @@ class TfqSimulateSampledExpectationOp : public tensorflow::OpKernel {
compute_status,
ComputeSampledExpectationQsim(
pauli_sums[cur_batch_index][cur_op_index], sim, ss, sv, scratch,
num_samples[cur_batch_index][cur_op_index], &exp_v),
num_samples[cur_batch_index][cur_op_index], gen, &exp_v),
c_lock);

(*output_tensor)(cur_batch_index, cur_op_index) = exp_v;
Expand Down
21 changes: 19 additions & 2 deletions tensorflow_quantum/core/ops/tfq_simulate_samples_op.cc
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ limitations under the License.

#include <stdlib.h>

#include <random>
#include <string>

#include "../qsim/lib/circuit.h"
Expand Down Expand Up @@ -143,6 +144,13 @@ class TfqSimulateSamplesOp : public tensorflow::OpKernel {
StateSpace ss = StateSpace(tfq_for);
auto sv = ss.Create(largest_nq);

unsigned long r_seed =
std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::system_clock::now().time_since_epoch())
.count();
std::mt19937 gen(r_seed);
std::uniform_int_distribution<> distrib(1, 1 << 30);

// Simulate programs one by one. Parallelizing over state vectors
// we no longer parallelize over circuits. Each time we encounter a
// a larger circuit we will grow the Statevector as nescessary.
Expand All @@ -159,7 +167,7 @@ class TfqSimulateSamplesOp : public tensorflow::OpKernel {
qsim::ApplyFusedGate(sim, fused_circuits[i][j], sv);
}

auto samples = ss.Sample(sv, num_samples, rand() % 123456);
auto samples = ss.Sample(sv, num_samples, distrib(gen));
for (int j = 0; j < num_samples; j++) {
uint64_t q_ind = 0;
uint64_t mask = 1;
Expand Down Expand Up @@ -190,11 +198,20 @@ class TfqSimulateSamplesOp : public tensorflow::OpKernel {
using Simulator = qsim::Simulator<const qsim::SequentialFor&>;
using StateSpace = Simulator::StateSpace;

unsigned long r_seed =
std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::system_clock::now().time_since_epoch())
.count();

auto DoWork = [&](int start, int end) {
int largest_nq = 1;
Simulator sim = Simulator(tfq_for);
StateSpace ss = StateSpace(tfq_for);
auto sv = ss.Create(largest_nq);

std::mt19937 gen(r_seed + start);
std::uniform_int_distribution<> distrib(1, 1 << 30);

for (int i = start; i < end; i++) {
int nq = num_qubits[i];

Expand All @@ -208,7 +225,7 @@ class TfqSimulateSamplesOp : public tensorflow::OpKernel {
qsim::ApplyFusedGate(sim, fused_circuits[i][j], sv);
}

auto samples = ss.Sample(sv, num_samples, rand() % 123456);
auto samples = ss.Sample(sv, num_samples, distrib(gen));
for (int j = 0; j < num_samples; j++) {
uint64_t q_ind = 0;
uint64_t mask = 1;
Expand Down
Loading

0 comments on commit 29a986d

Please sign in to comment.