Parallel calculations: Difference between revisions
Content added Content deleted
Puppydrum64 (talk | contribs) mNo edit summary |
(Added Wren) |
||
Line 2,678: | Line 2,678: | ||
} |
} |
||
puts "$best = [renderFactors [dict get $results $best]]"</lang> |
puts "$best = [renderFactors [dict get $results $best]]"</lang> |
||
=={{header|Wren}}== |
|||
{{trans|C}} |
|||
{{libheader|OpenMP}} |
|||
{{libheader|Wren-math}} |
|||
<br> |
|||
Although all Wren code runs within the context of a fiber (of which there can be thousands) only one fiber can run at a time and so the language's virtual machine (VM) is effectively single threaded. |
|||
However, it's possible for a suitable host on a suitable machine to run multiple VMs in parallel as the following example, with a C host, shows when run on a machine with four cores. Four VMs are used each of which runs on its own thread. |
|||
<lang ecmascript>/* parallel_calculations.wren */ |
|||
import "./math" for Int |
|||
class C { |
|||
static minPrimeFactor(n) { Int.primeFactors(n)[0] } |
|||
static allPrimeFactors(n) { Int.primeFactors(n) } |
|||
}</lang> |
|||
<br> |
|||
We now embed this Wren script in the following C program, compile and run it. |
|||
<lang c>#include <stdio.h> |
|||
#include <stdlib.h> |
|||
#include <string.h> |
|||
#include <omp.h> |
|||
#include "wren.h" |
|||
#define NUM_VMS 4 |
|||
WrenVM* vms[NUM_VMS]; // array of VMs |
|||
void doParallelCalcs() { |
|||
int data[] = {12757923, 12878611, 12878893, 12757923, 15808973, 15780709, 197622519}; |
|||
int i, count, largest, largest_factor = 0; |
|||
omp_set_num_threads(4); |
|||
// we can share the same call and class handles amongst VMs |
|||
WrenHandle* callHandle = wrenMakeCallHandle(vms[0], "minPrimeFactor(_)"); |
|||
WrenHandle* callHandle2 = wrenMakeCallHandle(vms[0], "allPrimeFactors(_)"); |
|||
wrenEnsureSlots(vms[0], 1); |
|||
wrenGetVariable(vms[0], "main", "C", 0); |
|||
WrenHandle* classHandle = wrenGetSlotHandle(vms[0], 0); |
|||
#pragma omp parallel for shared(largest_factor, largest) |
|||
for (i = 0; i < 7; ++i) { |
|||
int n = data[i]; |
|||
int vi = omp_get_thread_num(); // assign a VM (via its array index) for this number |
|||
wrenEnsureSlots(vms[vi], 2); |
|||
wrenSetSlotHandle(vms[vi], 0, classHandle); |
|||
wrenSetSlotDouble(vms[vi], 1, (double)n); |
|||
wrenCall(vms[vi], callHandle); |
|||
int p = (int)wrenGetSlotDouble(vms[vi], 0); |
|||
if (p > largest_factor) { |
|||
largest_factor = p; |
|||
largest = n; |
|||
printf("Thread %d: found larger: %d of %d\n", vi, p, n); |
|||
} else { |
|||
printf("Thread %d: not larger: %d of %d\n", vi, p, n); |
|||
} |
|||
} |
|||
printf("\nLargest minimal prime factor: %d of %d\n", largest_factor, largest); |
|||
printf("All prime factors for this number: "); |
|||
wrenEnsureSlots(vms[0], 2); |
|||
wrenSetSlotHandle(vms[0], 0, classHandle); |
|||
wrenSetSlotDouble(vms[0], 1, (double)largest); |
|||
wrenCall(vms[0], callHandle2); |
|||
count = wrenGetListCount(vms[0], 0); |
|||
for (i = 0; i < count; ++i) { |
|||
wrenGetListElement(vms[0], 0, i, 1); |
|||
printf("%d ", (int)wrenGetSlotDouble(vms[0], 1)); |
|||
} |
|||
printf("\n"); |
|||
wrenReleaseHandle(vms[0], callHandle); |
|||
wrenReleaseHandle(vms[0], callHandle2); |
|||
wrenReleaseHandle(vms[0], classHandle); |
|||
} |
|||
static void writeFn(WrenVM* vm, const char* text) { |
|||
printf("%s", text); |
|||
} |
|||
void errorFn(WrenVM* vm, WrenErrorType errorType, const char* module, const int line, const char* msg) { |
|||
switch (errorType) { |
|||
case WREN_ERROR_COMPILE: |
|||
printf("[%s line %d] [Error] %s\n", module, line, msg); |
|||
break; |
|||
case WREN_ERROR_STACK_TRACE: |
|||
printf("[%s line %d] in %s\n", module, line, msg); |
|||
break; |
|||
case WREN_ERROR_RUNTIME: |
|||
printf("[Runtime Error] %s\n", msg); |
|||
break; |
|||
} |
|||
} |
|||
char *readFile(const char *fileName) { |
|||
FILE *f = fopen(fileName, "r"); |
|||
fseek(f, 0, SEEK_END); |
|||
long fsize = ftell(f); |
|||
rewind(f); |
|||
char *script = malloc(fsize + 1); |
|||
fread(script, 1, fsize, f); |
|||
fclose(f); |
|||
script[fsize] = 0; |
|||
return script; |
|||
} |
|||
static void loadModuleComplete(WrenVM* vm, const char* module, WrenLoadModuleResult result) { |
|||
if( result.source) free((void*)result.source); |
|||
} |
|||
WrenLoadModuleResult loadModule(WrenVM* vm, const char* name) { |
|||
WrenLoadModuleResult result = {0}; |
|||
if (strcmp(name, "random") != 0 && strcmp(name, "meta") != 0) { |
|||
result.onComplete = loadModuleComplete; |
|||
char fullName[strlen(name) + 6]; |
|||
strcpy(fullName, name); |
|||
strcat(fullName, ".wren"); |
|||
result.source = readFile(fullName); |
|||
} |
|||
return result; |
|||
} |
|||
int main(int argc, char **argv) { |
|||
WrenConfiguration config; |
|||
wrenInitConfiguration(&config); |
|||
config.writeFn = &writeFn; |
|||
config.errorFn = &errorFn; |
|||
config.loadModuleFn = &loadModule; |
|||
const char* module = "main"; |
|||
const char* fileName = "parallel_calculations.wren"; |
|||
char *script = readFile(fileName); |
|||
// config the VMs and interpret the script |
|||
int i; |
|||
for (i = 0; i < NUM_VMS; ++i) { |
|||
vms[i] = wrenNewVM(&config); |
|||
wrenInterpret(vms[i], module, script); |
|||
} |
|||
doParallelCalcs(); |
|||
for (i = 0; i < NUM_VMS; ++i) wrenFreeVM(vms[i]); |
|||
free(script); |
|||
return 0; |
|||
}</lang> |
|||
{{out}} |
|||
Sample output as this will obviously vary depending on which threads return first and which of the three numbers (two the same) with a minimal prime factor of 47 is found first. |
|||
<pre> |
|||
Thread 0: found larger: 3 of 12757923 |
|||
Thread 2: found larger: 29 of 15808973 |
|||
Thread 0: found larger: 47 of 12878611 |
|||
Thread 2: not larger: 7 of 15780709 |
|||
Thread 1: not larger: 47 of 12878893 |
|||
Thread 1: not larger: 3 of 12757923 |
|||
Thread 3: not larger: 3 of 197622519 |
|||
Largest minimal prime factor: 47 of 12878611 |
|||
All prime factors for this number: 47 101 2713 |
|||
</pre> |
|||
{{out}} |
|||
Sample output when the other (distinct) number is found first. |
|||
<pre> |
|||
Thread 0: found larger: 3 of 12757923 |
|||
Thread 2: found larger: 29 of 15808973 |
|||
Thread 1: found larger: 47 of 12878893 |
|||
Thread 0: not larger: 47 of 12878611 |
|||
Thread 2: not larger: 7 of 15780709 |
|||
Thread 1: not larger: 3 of 12757923 |
|||
Thread 3: not larger: 3 of 197622519 |
|||
Largest minimal prime factor: 47 of 12878893 |
|||
All prime factors for this number: 47 274019 |
|||
</pre> |
|||
=={{header|zkl}}== |
=={{header|zkl}}== |