Skip to content

Commit

Permalink
deprecate mapMPAsync in favor of the C++ version
Browse files Browse the repository at this point in the history
  • Loading branch information
mmomtchev committed Jan 23, 2022
1 parent c777d95 commit 6d05897
Show file tree
Hide file tree
Showing 4 changed files with 1 addition and 127 deletions.
14 changes: 0 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -143,9 +143,6 @@ const r = await mean.evalAsync(inputArray);
* [map](#map)
* [Parameters](#parameters-2)
* [Examples](#examples-2)
* [mapMPAsync](#mapmpasync)
* [Parameters](#parameters-3)
* [Examples](#examples-3)
* [reduce](#reduce)
* [Parameters](#parameters-4)
* [Examples](#examples-4)
Expand Down Expand Up @@ -318,17 +315,6 @@ expr.mapAsync(array, 'x', {f: 0, c: 0}, (e,r) => console.log(e, r));

Returns **TypedArray\<T>**&#x20;

## mapMPAsync

Evaluate the expression for every element of a TypedArray
distributing the array over multiple threads.

All arrays must match the internal data type.

If target is specified, it will write the data into a preallocated array.
This can be used when multiple operations are chained to avoid reallocating a new array at every step.
Otherwise it will return a new array.

### Parameters

* `target` **TypedArray\<T>?** array in which the data is to be written
Expand Down
7 changes: 1 addition & 6 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,19 +49,14 @@ export class Expression<T> {
mapAsync(threads: number, target: T, array: T, iterator: string, arguments: Record<string, number | T>, callback: (this: Expression<T>, e: Error | null, r: T | undefined) => void): void;


mapMPAsync(array: T, threads: number, iterator: string, arguments: Record<string, number | T>): Promise<T>;
mapMPAsync(array: T, threads: number, iterator: string, ...arguments: (number | T)[]): Promise<T>;
mapMPAsync(target: T, array: T, threads: number, iterator: string, arguments: Record<string, number | T>): Promise<T>;
mapMPAsync(target: T, array: T, threads: number, iterator: string, ...arguments: (number | T)[]): Promise<T>;


reduce(array: T, iterator: string, accumulator: string, initializer: number, arguments: Record<string, number | T>): number;
reduce(array: T, iterator: string, accumulator: string, initializer: number, ...arguments: (number | T)[]): number;

reduceAsync(array: T, iterator: string, accumulator: string, initializer: number, arguments: Record<string, number | T>): Promise<number>;
reduceAsync(array: T, iterator: string, accumulator: string, initializer: number, ...arguments: (number | T)[]): Promise<number>;
reduceAsync(array: T, iterator: string, accumulator: string, initializer: number, arguments: Record<string, number | T>, callback: (this: Expression<T>, e: Error | null, r: number | undefined) => void): void


cwise(arguments: Record<string, number | TypedArray>): T;
cwise<U extends TypedArray>(arguments: Record<string, number | TypedArray>, result: U): U;

Expand Down
59 changes: 0 additions & 59 deletions lib/binding.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,70 +23,11 @@ const promisifiables = [
'cwiseAsync'
];

/**
* Evaluate the expression for every element of a TypedArray
* distributing the array over multiple threads.
*
* All arrays must match the internal data type.
*
* If target is specified, it will write the data into a preallocated array.
* This can be used when multiple operations are chained to avoid reallocating a new array at every step.
* Otherwise it will return a new array.
*
* @param {TypedArray<T>} [target] array in which the data is to be written
* @param {TypedArray<T>} array for the expression to be iterated over
* @param {number} threads number, must not exceed Expression.maxParallel
* @param {string} iterator variable name
* @param {...(number|TypedArray<T>)[]|Record<string, number|TypedArray<T>>} arguments of the function, iterator removed
* @returns {TypedArray<T>}
* @memberof Expression
*
* @example
* // Clamp values in an array to [0..1000]
* const expr = new Expression('clamp(f, x, c)', ['f', 'x', 'c']);
*
* await expr.mapMPAsync(array, expr.maxParallel, 'x', 0, 1000);
*/
function mapMPAsync() {
let array, target, threads, parameters;

if (typeof arguments[0] === 'object' && typeof arguments[0].length === 'number' &&
typeof arguments[1] === 'number') {
array = arguments[0];
threads = arguments[1];
target = new array.constructor(array.length);
parameters = Array.prototype.slice.call(arguments, 2);
} else if (typeof arguments[0] === 'object' && typeof arguments[0].length === 'number' &&
typeof arguments[1] === 'object' && typeof arguments[1].length === 'number' &&
typeof arguments[2] === 'number') {
target = arguments[0];
array = arguments[1];
threads = arguments[2];
parameters = Array.prototype.slice.call(arguments, 3);
} else {
return Promise.reject('invalid arguments');
}
if (!(threads > 0 && threads <= this.maxParallel)) return Promise.reject('threads must not exceed maxParallel');

const chunkSize = Math.ceil(array.length / threads);

const q = [];
for (let start = 0, end = start + chunkSize;
start < array.length;
start = end, end = Math.min(start + chunkSize, array.length)) {

q.push(this.mapAsync.apply(this, [target.subarray(start, end), array.subarray(start, end), ...parameters]));
}

return Promise.all(q).then(() => target);
}

for (const t of types) {
if (addon[t] === undefined) {
console.warn(`${t} type not built`);
continue;
}
addon[t].prototype.mapMPAsync = mapMPAsync;
for (const m of promisifiables) {
addon[t].prototype[m] = (function () {
const promisified = promisify(addon[t].prototype[m]);
Expand Down
48 changes: 0 additions & 48 deletions test/expr.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -711,54 +711,6 @@ describe('Expression', () => {
/at least one argument must be a non-zero length vector/);
});
});

describe('mapMPAsync()', () => {
const big = 128 * 1024;
let array: Float64Array, plus: Float64;
before(() => {
array = new Float64Array(big);
for (let i = 0; i < big; i++) array[i] = i;
plus = new expr('a + b');
});

it('should evaluate an expression with multiple parallel instances', () => {
const q = plus.mapMPAsync(array, expr.maxParallel, 'a', 12);
return assert.isFulfilled(q.then((r) => {
assert.instanceOf(r, Float64Array);
assert.equal(r.length, big);
for (let i = 0; i < big; i += big / 1024)
assert.closeTo(r[i], i + 12, 10e-9);
}));
});

it('should support writing into a preallocated array', () => {
const dst = new Float64Array(big);
const q = plus.mapMPAsync(dst, array, expr.maxParallel, 'a', 12);
return assert.isFulfilled(q.then((r) => {
assert.strictEqual(dst, r);
assert.equal(r.length, big);
for (let i = 0; i < big; i += big / 1024)
assert.closeTo(r[i], i + 12, 10e-9);
}));
});

it('should reject if the array sizes do not match', () => {
const dst = new Float64Array(big / 2);
const q = plus.mapMPAsync(dst, array, expr.maxParallel, 'a', 12);
return assert.isRejected(q, /same size/);
});

it('should reject if the arguments are invalid', () => {
const q = plus.mapMPAsync({} as Float64Array, expr.maxParallel, 'a', 12);
return assert.isRejected(q, /invalid arguments/);
});

it('should reject if the number of threads is invalid', () => {
const dst = new Float64Array(big);
const q = plus.mapMPAsync(dst, array, expr.maxParallel + 1, 'a', 12);
return assert.isRejected(q, /exceed maxParallel/);
});
});
});

describe('cwise()/cwiseAsync() type conversions', () => {
Expand Down

0 comments on commit 6d05897

Please sign in to comment.