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

GPU バックエンドテンプレート #352

Draft
wants to merge 15 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,739 changes: 870 additions & 869 deletions apps/tutorial/application.js

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions apps/tutorial/application.js.map

Large diffs are not rendered by default.

174 changes: 108 additions & 66 deletions apps/www/app/assets/javascripts/serviceworker.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ function runSimulator(e) {
const targets = e.data.targets
const invalidateCaches = e.data.invalidateCaches
const debug = e.data.debug
const backend = e.data.backend

Util.notNull(qubitCount)
Util.notNull(stepIndex)
Expand All @@ -28,98 +29,139 @@ function runSimulator(e) {
)
}

const s_time = new Date()
const simulator = new Simulator('0'.repeat(qubitCount))
if (backend) {
runBackend(circuitJson, qubitCount, stepIndex, steps, targets, backend)
} else {
const s_time = new Date()
const simulator = new Simulator('0'.repeat(qubitCount))

if (resultCache[circuitJson] === undefined || invalidateCaches) {
resultCache = {}
resultCache[circuitJson] = {}
}
if (resultCache[circuitJson] === undefined || invalidateCaches) {
resultCache = {}
resultCache[circuitJson] = {}
}

let cacheHit = false
let cacheHit = false

for (const [i, operations] of steps.entries()) {
let stepResult = {}
for (const [i, operations] of steps.entries()) {
let stepResult = {}

if (resultCache[circuitJson][i] === undefined) {
resultCache[circuitJson][i] = {}
}
const cachedStepResult = resultCache[circuitJson][i]

if (
cachedStepResult === undefined ||
cachedStepResult.targets === undefined ||
cachedStepResult.targets.length < targets.length
) {
cacheHit = false

simulator.runStep(operations)

const allAmplitudes = simulator.state.matrix.clone()
const blochVectors = Object.assign({}, simulator.blochVectors)
const measuredBits = Object.assign({}, simulator.measuredBits)
const flags = Object.assign({}, simulator.flags)

resultCache[circuitJson][i] = {
type: 'step',
step: i,
amplitudes: allAmplitudes,
targets,
blochVectors,
measuredBits,
flags,
if (resultCache[circuitJson][i] === undefined) {
resultCache[circuitJson][i] = {}

Check warning

Code scanning / CodeQL

Prototype-polluting assignment

This assignment may alter Object.prototype if a malicious '__proto__' string is injected from [user controlled input](1).
}
const cachedStepResult = resultCache[circuitJson][i]

if (i === stepIndex) {
const amplitudes = pickTargetAmplitudes(targets, allAmplitudes)
if (
cachedStepResult === undefined ||
cachedStepResult.targets === undefined ||
cachedStepResult.targets.length < targets.length
) {
cacheHit = false

stepResult = {
simulator.runStep(operations)

const allAmplitudes = simulator.state.matrix.clone()
const blochVectors = Object.assign({}, simulator.blochVectors)
const measuredBits = Object.assign({}, simulator.measuredBits)
const flags = Object.assign({}, simulator.flags)

resultCache[circuitJson][i] = {

Check warning

Code scanning / CodeQL

Prototype-polluting assignment

This assignment may alter Object.prototype if a malicious '__proto__' string is injected from [user controlled input](1).
type: 'step',
step: i,
amplitudes,
amplitudes: allAmplitudes,
targets,
blochVectors,
measuredBits,
flags,
}

if (i === stepIndex) {
const amplitudes = pickTargetAmplitudes(targets, allAmplitudes)

stepResult = {
type: 'step',
step: i,
amplitudes,
blochVectors,
measuredBits,
flags,
}
} else {
stepResult = {
type: 'step',
step: i,
amplitudes: [],
blochVectors,
measuredBits,
flags,
}
}
} else {
cacheHit = true

stepResult = {
type: 'step',
step: i,
amplitudes: [],
blochVectors,
measuredBits,
flags,
blochVectors: cachedStepResult.blochVectors,
measuredBits: cachedStepResult.measuredBits,
flags: cachedStepResult.flags,
}
}
} else {
cacheHit = true

stepResult = {
type: 'step',
step: i,
amplitudes: [],
blochVectors: cachedStepResult.blochVectors,
measuredBits: cachedStepResult.measuredBits,
flags: cachedStepResult.flags,
}

if (i === stepIndex) {
stepResult.amplitudes = pickTargetAmplitudes(targets, cachedStepResult.amplitudes)
if (i === stepIndex) {
stepResult.amplitudes = pickTargetAmplitudes(targets, cachedStepResult.amplitudes)
}
}

self.postMessage(stepResult)
}

self.postMessage(stepResult)
}
const e_time = new Date()
const diff = e_time.getTime() - s_time.getTime()
const cacheDesc = cacheHit ? '🎯 CACHE HIT' : '💦 CACHE MISS'
if (debug) {
// eslint-disable-next-line no-console
console.log(`⏱ simulation took ${diff} msec (${cacheDesc})`)
}

const e_time = new Date()
const diff = e_time.getTime() - s_time.getTime()
const cacheDesc = cacheHit ? '🎯 CACHE HIT' : '💦 CACHE MISS'
if (debug) {
// eslint-disable-next-line no-console
console.log(`⏱ simulation took ${diff} msec (${cacheDesc})`)
self.postMessage({type: 'finish'})
}
}

self.postMessage({type: 'finish'})
function runBackend(json, qubitCount, stepIndex, steps, targets, backend) {
const params = new URLSearchParams({
id: json,
qubitCount: qubitCount,
stepIndex: stepIndex,
steps: JSON.stringify(steps),
targets: targets,
backend: backend,
})

fetch(`/backend.json?${params}`, {
method: 'GET',
})
.then(response => {
if (!response.ok) {
throw new Error("Failed to connect to Qni's backend endpoint.")
}
return response.json()
})
.then(response => {
for (let i = 0; i < response.length; i++) {
const stepResult = response[i]
self.postMessage({
type: 'step',
step: i,
amplitudes: stepResult['amplitudes'],
blochVectors: stepResult['blochVectors'],
measuredBits: stepResult['measuredBits'],
flags: {},
})
}
})
.catch(error => {
console.error(error)
})
}

const pickTargetAmplitudes = (targets, amplitudes) => {
Expand Down
26 changes: 26 additions & 0 deletions apps/www/app/controllers/backend_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# frozen_string_literal: true

require 'cu_quantum'

class BackendController < ApplicationController
# rubocop:disable Metrics/AbcSize
# rubocop:disable Metrics/MethodLength
def show
backend = params[:backend]
circuit_id = params[:id]
qubit_count = params[:qubitCount].to_i
step_index = params[:stepIndex].to_i
steps = params[:steps] ? JSON.parse(params[:steps]) : []
targets = params[:targets].split(',').map(&:to_i) if params[:targets]

raise "Unsupported backend: #{backend}" unless backend == 'cu_quantum'

@step_results = CuQuantum.new(circuit_id: circuit_id,
qubit_count: qubit_count,
step_index: step_index,
steps: steps,
targets: targets).run
end
# rubocop:enable Metrics/AbcSize
# rubocop:enable Metrics/MethodLength
end
5 changes: 5 additions & 0 deletions apps/www/app/controllers/cu_quantum_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# frozen_string_literal: true

class CuQuantumController < ApplicationController
def show; end
end
1 change: 1 addition & 0 deletions apps/www/app/views/backend/show.json.jbuilder
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
json.array! @step_results
Loading