Program.hpp 6.33 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
/***********************************************************************************
 * Copyright (c) 2016, UT-Battelle
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
12
 *   * Neither the name of the xacc nor the
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
 *     names of its contributors may be used to endorse or promote products
 *     derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Contributors:
 *   Initial API and implementation - Alex McCaskey
 *
 **********************************************************************************/
#ifndef XACC_PROGRAM_HPP_
#define XACC_PROGRAM_HPP_

#include <string>
#include <vector>
36
#include <fstream>
37
38
#include <memory>
#include <queue>
39
#include <boost/algorithm/string.hpp>
40
#include <algorithm>
41
42

#include "Utils.hpp"
43
44
#include "Compiler.hpp"
#include "Accelerator.hpp"
45
#include "RuntimeOptions.hpp"
46
#include "Preprocessor.hpp"
47
#include "ServiceRegistry.hpp"
48
49
50

namespace xacc {

51
52
53
54
55
/**
 * Placeholder, soon we will have Acc Independent transformations...
 * @param accType
 * @return
 */
56
57
58
59
60
61
std::vector<IRTransformation> getAcceleratorIndependentTransformations(
		AcceleratorType& accType) {
	std::vector<IRTransformation> transformations;
	return transformations;
}

62
63
std::vector<std::shared_ptr<Preprocessor>> getDefaultPreprocessors(
		AcceleratorType accType) {
64
	std::vector<std::shared_ptr<Preprocessor>> preprocessors;
65
66
	auto preprocessor = ServiceRegistry::instance()->getService<Preprocessor>(
			"kernel-replacement");
67
	if (accType == AcceleratorType::qpu_gate) {
68
		preprocessors.push_back(preprocessor);
69
70
71
72
73
	}

	return preprocessors;
}

74
/**
75
 * The Program is the main entrypoint for the XACC
76
77
78
79
80
 * API. Users with accelerator kernels must construct a
 * valid Program to be compiled and executed on the
 * attached accelerator. Programs must be given the
 * Accelerator reference to be used and kernel source
 * code at construction time.
81
82
83
84
85
 */
class Program {

protected:

86
87
88
89
	/**
	 * Reference to the source accelerator
	 * kernel code to be compiled and executed
	 */
90
91
	std::string src;

92
93
94
95
	/**
	 * Reference to the attached Accelerator to
	 * use in this compilation and execution
	 */
96
	std::shared_ptr<Accelerator> accelerator;
97

98
	/**
99
100
	 * Reference to the XACC IR instance that is
	 * created by the Compiler
101
	 */
102
103
	std::shared_ptr<IR> xaccIR;

104
105
106
	/**
	 * Reference to the compiler
	 */
107
	std::shared_ptr<Compiler> compiler;
108

109
110
111
112
113
114
	/**
	 * Execute the compilation mechanism on the provided program
	 * source kernel code to produce XACC IR that can be executed
	 * on the attached Accelerator.
	 *
	 */
115
	void build() {
116

117
		// Get reference to the runtime options
118
		auto runtimeOptions = RuntimeOptions::instance();
119

120
121
		// Get the compiler that has been requested.
		auto compilerToRun = (*runtimeOptions)["compiler"];
122
123

		// Create the appropriate compiler
124
125
		compiler = xacc::ServiceRegistry::instance()->getService<Compiler>(
				compilerToRun);
126

127
128
		// Make sure we got a valid
		if (!compiler) {
129
			XACCError("Invalid Compiler.\n");
130
131
		}

132
133
134
135
136
		// Before compiling, run preprocessors
		auto defaultPPs = getDefaultPreprocessors(accelerator->getType());
		for (auto preprocessor : defaultPPs) {
			src = preprocessor->process(src, compiler, accelerator);
		}
137

138
139
		XACCInfo("Executing "+ compiler->getName() + " compiler.");

140
		// Execute the compilation
141
		xaccIR = compiler->compile(src, accelerator);
142
143

		// Validate the compilation
144
		if (!xaccIR) {
145
			XACCError("Bad source string or something.\n");
146
147
		}

148
		// Write the IR to file if the user requests it
149
150
		if (runtimeOptions->exists("persist-ir")) {
			auto fileStr = (*runtimeOptions)["persist-ir"];
151
152
153
154
			std::ofstream ostr(fileStr);
			xaccIR->persist(ostr);
		}

155
		return;
156
157
	}

158
159
160
161
162
163
164
165
166
167
public:

	/**
	 * The Constructor, takes the Accelerator
	 * to execute on, and the source to compile and execute
	 *
	 * @param acc Attached Accelerator to execute
	 * @param sourceFile The kernel source code
	 */
	Program(std::shared_ptr<Accelerator> acc, const std::string& sourceFile) :
168
			src(sourceFile), accelerator(std::move(acc)) {
169
170
	}

171
	/**
172
173
	 * Return an executable version of the quantum kernel
	 * referenced by the kernelName string.
174
175
176
177
178
	 *
	 * @param name
	 * @param args
	 * @return
	 */
179
	template<typename ... RuntimeArgs>
180
181
	std::function<void(std::shared_ptr<AcceleratorBuffer>, RuntimeArgs...)> getKernel(
			const std::string& kernelName) {
182
183
184
185
186

		// Build the kernel with the appropriate compiler
		build();

		// Create a lambda that executes the kernel on the Accelerator.
187
		return std::move([=](std::shared_ptr<AcceleratorBuffer> buffer, RuntimeArgs... args) {
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209

			// Get the Function for the Kernel from the IR
			auto kernel = xaccIR->getKernel(kernelName);

			if (sizeof...(RuntimeArgs) > 0) {
				// Store the runtime parameters in a tuple
				auto argsTuple = std::make_tuple(args...);

				// Loop through the tuple, and add InstructionParameters
				// to the parameters vector.
				std::vector<InstructionParameter> parameters;
				xacc::tuple_for_each(argsTuple, [&](auto value) {
					parameters.push_back(InstructionParameter(value));
				});

				// Evaluate all Variable Parameters
				kernel->evaluateVariableParameters(parameters);
			}

			// Execute the Kernel on the Accelerator
			accelerator->execute(buffer, kernel);

210
			return;
211
		});
212
	}
213
214
215
216
};

}
#endif