bstring parse_workgroup(Workgroup* group, const_bstring str, DataType type) { CpuTopology_t topo; struct bstrList* tokens; bstring cpustr; int numThreads = 0; bstring domain; tokens = bsplit(str,':'); if (tokens->qty == 2) { topo = get_cpuTopology(); numThreads = topo->activeHWThreads; cpustr = bformat("E:%s:%d", bdata(tokens->entry[0]), numThreads ); } else if (tokens->qty == 3) { cpustr = bformat("E:%s:%s", bdata(tokens->entry[0]), bdata(tokens->entry[2])); numThreads = str2int(bdata(tokens->entry[2])); if (numThreads < 0) { fprintf(stderr, "Cannot convert %s to integer\n", bdata(tokens->entry[2])); bstrListDestroy(tokens); return NULL; } } else if (tokens->qty == 5) { cpustr = bformat("E:%s:%s:%s:%s", bdata(tokens->entry[0]), bdata(tokens->entry[2]), bdata(tokens->entry[3]), bdata(tokens->entry[4])); numThreads = str2int(bdata(tokens->entry[2])); if (numThreads < 0) { fprintf(stderr, "Cannot convert %s to integer\n", bdata(tokens->entry[2])); bstrListDestroy(tokens); return NULL; } } else { fprintf(stderr, "Misformated workgroup string\n"); bstrListDestroy(tokens); return NULL; } group->size = bstr_to_doubleSize(tokens->entry[1], type); if (group->size == 0) { fprintf(stderr, "Stream size cannot be read, should look like <domain>:<size>\n"); bstrListDestroy(tokens); return NULL; } group->processorIds = (int*) malloc(numThreads * sizeof(int)); if (group->processorIds == NULL) { fprintf(stderr, "No more memory to allocate list of processors\n"); bstrListDestroy(tokens); return NULL; } group->numberOfThreads = numThreads; if (cpustr_to_cpulist(bdata(cpustr),group->processorIds, numThreads) < 0 ) { free(group->processorIds); bstrListDestroy(tokens); return NULL; } domain = bstrcpy(tokens->entry[0]); bdestroy(cpustr); bstrListDestroy(tokens); return domain; }
void bstr_to_workgroup(Workgroup* group, const_bstring str, DataType type, int numberOfStreams) { uint32_t i; int parseStreams = 0; bstring threadInfo; bstring streams= bformat("0"); struct bstrList* tokens; struct bstrList* subtokens; AffinityDomains_t domains; AffinityDomain* domain = NULL; /* split the workgroup into the thread and the streams part */ tokens = bsplit(str,'-'); if (tokens->qty == 2) { threadInfo = bstrcpy(tokens->entry[0]); streams = bstrcpy(tokens->entry[1]); parseStreams = 1; } else if (tokens->qty == 1) { threadInfo = bstrcpy(tokens->entry[0]); } else { fprintf(stderr, "Error in parsing workgroup string\n"); } bstrListDestroy (tokens); tokens = bsplit(threadInfo,':'); if (tokens->qty == 5) { uint32_t maxNumThreads; int chunksize; int stride; int counter; int currentId = 0; int startId = 0; domains = get_affinityDomains(); for (i = 0; i < domains->numberOfAffinityDomains; i++) { if (bstrcmp(domains->domains[i].tag, tokens->entry[0]) == BSTR_OK) { domain = &(domains->domains[i]); break; } } if (domain == NULL) { fprintf(stderr, "Error: Domain %s not available on current machine.\nTry likwid-bench -p for supported domains.", bdata(tokens->entry[0])); exit(EXIT_FAILURE); } group->size = bstr_to_doubleSize(tokens->entry[1], type); group->numberOfThreads = str2int(bdata(tokens->entry[2])); chunksize = str2int(bdata(tokens->entry[3])); stride = str2int(bdata(tokens->entry[4])); maxNumThreads = ceil((double)domain->numberOfProcessors / stride) * chunksize; if (group->numberOfThreads > maxNumThreads) { fprintf(stderr, "Warning: More threads (%d) requested than CPUs in domain %s fulfilling expression (%d).\n", group->numberOfThreads, bdata(tokens->entry[0]), maxNumThreads); } group->processorIds = (int*) malloc(group->numberOfThreads * sizeof(int)); counter = chunksize; counter = 0; for (int j=0; j<group->numberOfThreads; j+=chunksize) { for(i=0;i<chunksize && j+i<group->numberOfThreads ;i++) { group->processorIds[startId++] = domain->processorList[counter+i]; } counter += stride; if (counter >= domain->numberOfProcessors) { counter = counter-domain->numberOfProcessors; } } } else if (tokens->qty == 3) { domains = get_affinityDomains(); for (i = 0; i < domains->numberOfAffinityDomains; i++) { if (bstrcmp(domains->domains[i].tag, tokens->entry[0]) == BSTR_OK) { domain = &(domains->domains[i]); break; } } if (domain == NULL) { fprintf(stderr, "Error: Domain %s not available on current machine.\nTry likwid-bench -p for supported domains.", bdata(tokens->entry[0])); exit(EXIT_FAILURE); } group->size = bstr_to_doubleSize(tokens->entry[1], type); group->numberOfThreads = str2int(bdata(tokens->entry[2])); if (group->numberOfThreads > domain->numberOfProcessors) { fprintf(stderr, "Warning: More threads (%d) requested than CPUs in domain %s (%d).\n", group->numberOfThreads, bdata(tokens->entry[0]), domain->numberOfProcessors); } group->processorIds = (int*) malloc(group->numberOfThreads * sizeof(int)); for (i=0; i<group->numberOfThreads; i++) { group->processorIds[i] = domain->processorList[i % domain->numberOfProcessors]; } } else if (tokens->qty == 2) { domains = get_affinityDomains(); for (i = 0; i < domains->numberOfAffinityDomains; i++) { if (bstrcmp(domains->domains[i].tag, tokens->entry[0]) == BSTR_OK) { domain = &(domains->domains[i]); break; } } if (domain == NULL) { fprintf(stderr, "Error: Domain %s not available on current machine.\nTry likwid-bench -p for supported domains.", bdata(tokens->entry[0])); exit(EXIT_FAILURE); } group->size = bstr_to_doubleSize(tokens->entry[1], type); group->numberOfThreads = domain->numberOfProcessors; group->processorIds = (int*) malloc(group->numberOfThreads * sizeof(int)); for (i=0; i<group->numberOfThreads; i++) { group->processorIds[i] = domain->processorList[i]; } } else { fprintf(stderr, "Error in parsing workgroup string\n"); } bstrListDestroy(tokens); /* parse stream list */ if (parseStreams) { tokens = bsplit(streams,','); if (tokens->qty < numberOfStreams) { fprintf(stderr, "Error: Testcase requires at least %d streams\n", numberOfStreams); } group->streams = (Stream*) malloc(numberOfStreams * sizeof(Stream)); for (i=0;i<(uint32_t) tokens->qty;i++) { subtokens = bsplit(tokens->entry[i],':'); if ( subtokens->qty == 3 ) { int index = str2int(bdata(subtokens->entry[0])); if (index >= numberOfStreams) { fprintf(stderr, "Error: Stream index %d out of range\n",index); } group->streams[index].domain = bstrcpy(subtokens->entry[1]); group->streams[index].offset = str2int(bdata(subtokens->entry[2])); } else if ( subtokens->qty == 2 ) { int index = str2int(bdata(subtokens->entry[0])); if (index >= numberOfStreams) { fprintf(stderr, "Error: Stream index %d out of range\n",index); } group->streams[index].domain = bstrcpy(subtokens->entry[1]); group->streams[index].offset = 0; } else { fprintf(stderr, "Error: Cannot parse stream placement defintition in %s\n", bdata(str)); } bstrListDestroy(subtokens); } bstrListDestroy(tokens); } else { group->streams = (Stream*) malloc(numberOfStreams * sizeof(Stream)); for (i=0; i< (uint32_t)numberOfStreams; i++) { group->streams[i].domain = domain->tag; group->streams[i].offset = 0; } } group->size /= numberOfStreams; return; }