From: K. A. <k_a...@ya...> - 2012-08-21 20:56:38
|
Hi David, Terry, The manual lists abolish_all_private_tables/0 (in Chapter 6) as a "standard predicate", described on p. 100 as predicates "which are always available to the Prolog interpreter and do not need to be imported or loaded explicitly as do other Prolog predicates." Terry has volunteered to fix that in the manual (thanks!). I've run into what appears to be a threading bug though, which I hope that Terry can shed some light on. Per Terry's suggestion, I've declared privately tabled versions of all my shared dynamic predicates, by appending the capital letter 'P' at the end of each predicate's name (e.g., if I have a shared dynamic predicate 'before' then I introduce a privately tabled predicate 'beforeP'). Then I define the privately tabled versions to be supersets of the shared ones (again, as Terry suggested), e.g.: beforeP(X,Y,Z) :- before(X,Y,Z). However, I'm running into another thread issue, which is (again) a discepancy between doing something on the main thread and doing the exact same thing on a spawned thread. This time I was able to reproduce the problem in pure XSB - no C involved. Consider the following interaction with XSB: consult('prelude.P'). assert(parentOf(a,b,[])). findall(X/Y/L,familyOfP(X,Y,L),R), write(R). (See below for the contents of prelude.P.) This works fine (because it's done on the main thread): it correctly reasons out that a is familyOfP b, b is familyOfP a, etc. Now I *should* get the same result when I evaluate this query on a spawned thread. But I don't. When I do: consult('prelude.P'). assert(parentOf(a,b,[])). thread_create((findall(X/Y/L,familyOfP(X,Y,L),R),Id), thread_join(Id,ExitCode). I get the following odd error: | ?- thread_create((findall(X/Y/L,familyOfP(X,Y,L),R),write(R)),Id), thread_join(Id,ExitCode). ++Error[XSB/Runtime/P]: [Miscellaneous] [th 1] Floundering goal in tnot/1 familyOfP(_v185356496 X = _h171 Y = _h185 L = _h199 R = _h261 Id = 1 ExitCode = exception(error(misc_error,[th 1] Floundering goal in tnot/1 familyOfP(_v185356496,[[Forward Continuation...,... standard:call/1,... standard:call_c/1,... standard:call/1,... standard:call/1],Backward Continuation...])) This is especially perplexing given that there is no negation anywhere, tabled or otherwise. How/where does floundering enter the picture? I've actually run into a number of such "floundering" errors recently while trying to do seemingly innocuous things on spawned threads. (I've forwarded some such errors before to David, though we were both stumped by the nature of the error message.) Again, I've only seen such errors on spawned threads, never on the main XSB thread. Clarification/feedback would be appreciated. Thanks, Konstantine The contents of prelude.P are pasted below. Most of this stuff is irrelevant to the problem, but I've spent the last 3 hours throwing away the majority of the stuff from prelude.P. What's left is, I think, pretty manageable and readable: :- import append/3 from basics. appendAll([],[]). appendAll([H|T],L) :- appendAll(T,L1), append(H,L1,L). append3(L1,L2,L3,L) :- append(L1,L2,R), append(L3,R,L). append4(L1,L2,L3,L4,L) :- append3(L1,L2,L3,R), append(L4,R,L). append5(L1,L2,L3,L4,L5,L) :- append4(L1,L2,L3,L4,R), append(L5,R,L). /***************************************************************************** Private tabled predicate declarations ******************************************************************************/ :- table afterP/3 as private. :- table beforeP/3 as private. :- table dateAfterP/3 as private. :- table dateBeforeP/3 as private. :- table intervalAfterP/3 as private. :- table intervalBeforeP/3 as private. :- table differentFromP/3 as private. :- table knowsOfP/3 as private. :- table relatedPersonOfP/3 as private. :- table familyOfP/3 as private. :- table auntOfP/3 as private. :- table cousinOfP/3 as private. :- table nephewOfP/3 as private. :- table nieceOfP/3 as private. :- table uncleOfP/3 as private. :- table ancestorOfP/3 as private. :- table grandParentOfP/3 as private. :- table grandMotherOfP/3 as private. :- table grandFatherOfP/3 as private. :- table parentOfP/3 as private. :- table fatherOfP/3 as private. :- table motherOfP/3 as private. :- table descendantOfP/3 as private. :- table childOfP/3 as private. :- table daughterOfP/3 as private. :- table sonOfP/3 as private. :- table grandChildOfP/3 as private. :- table grandsonOfP/3 as private. :- table granddaughterOfP/3 as private. :- table inLawOfP/3 as private. :- table brotherInLawOfP/3 as private. :- table daughterInLawOfP/3 as private. :- table fatherInLawOfP/3 as private. :- table motherInLawOfP/3 as private. :- table sisterInLawOfP/3 as private. :- table sonInLawOfP/3 as private. :- table siblingOfP/3 as private. :- table brotherOfP/3 as private. :- table sisterOfP/3 as private. :- table spouseOfP/3 as private. :- table husbandOfP/3 as private. :- table wifeOfP/3 as private. :- table unknownPersonRelationP/3 as private. :- table endsInDateP/3 as private. :- table startsInDateP/3 as private. :- table expirationDateP/3 as private. :- table hasLocationP/3 as private. :- table ownedByP/3 as private. :- table involvedP/3 as private. :- table occursInP/3 as private. :- table occursDuringP/3 as private. :- table operationAreaP/3 as private. :- table ownerOfP/3 as private. :- table relatedEventP/3 as private. :- table teacherP/3 as private. :- table relationObjectP/3 as private. :- table studentP/3 as private. :- table ageP/3 as private. :- table dateDayP/3 as private. :- table dateMonthP/3 as private. :- table dateYearP/3 as private. :- table descriptionP/3 as private. :- table dateP/1 as private. :- table dateIntervalP/1 as private. :- table eventP/1 as private. :- table locationP/1 as private. :- table cityP/1 as private. :- table countryP/1 as private. :- table regionP/1 as private. :- table stateP/1 as private. /***************************************************************************** Dynamic predicate declarations ******************************************************************************/ :- dynamic after/3 as shared. :- dynamic before/3 as shared. :- dynamic dateAfter/3 as shared. :- dynamic dateBefore/3 as shared. :- dynamic intervalAfter/3 as shared. :- dynamic intervalBefore/3 as shared. :- dynamic differentFrom/3 as shared. :- dynamic knowsOf/3 as shared. :- dynamic relatedPersonOf/3 as shared. :- dynamic familyOf/3 as shared. :- dynamic auntOf/3 as shared. :- dynamic cousinOf/3 as shared. :- dynamic nephewOf/3 as shared. :- dynamic nieceOf/3 as shared. :- dynamic uncleOf/3 as shared. :- dynamic ancestorOf/3 as shared. :- dynamic grandParentOf/3 as shared. :- dynamic grandMotherOf/3 as shared. :- dynamic grandFatherOf/3 as shared. :- dynamic parentOf/3 as shared. :- dynamic fatherOf/3 as shared. :- dynamic motherOf/3 as shared. :- dynamic descendantOf/3 as shared. :- dynamic childOf/3 as shared. :- dynamic daughterOf/3 as shared. :- dynamic sonOf/3 as shared. :- dynamic grandChildOf/3 as shared. :- dynamic grandsonOf/3 as shared. :- dynamic granddaughterOf/3 as shared. :- dynamic inLawOf/3 as shared. :- dynamic brotherInLawOf/3 as shared. :- dynamic daughterInLawOf/3 as shared. :- dynamic fatherInLawOf/3 as shared. :- dynamic motherInLawOf/3 as shared. :- dynamic sisterInLawOf/3 as shared. :- dynamic sonInLawOf/3 as shared. :- dynamic siblingOf/3 as shared. :- dynamic brotherOf/3 as shared. :- dynamic sisterOf/3 as shared. :- dynamic spouseOf/3 as shared. :- dynamic husbandOf/3 as shared. :- dynamic wifeOf/3 as shared. :- dynamic unknownPersonRelation/3 as shared. :- dynamic endsInDate/3 as shared. :- dynamic startsInDate/3 as shared. :- dynamic expirationDate/3 as shared. :- dynamic hasLocation/3 as shared. :- dynamic ownedBy/3 as shared. :- dynamic involved/3 as shared. :- dynamic occursIn/3 as shared. :- dynamic occursDuring/3 as shared. :- dynamic operationArea/3 as shared. :- dynamic ownerOf/3 as shared. :- dynamic relatedEvent/3 as shared. :- dynamic teacher/3 as shared. :- dynamic relationObject/3 as shared. :- dynamic student/3 as shared. :- dynamic age/3 as shared. :- dynamic dateDay/3 as shared. :- dynamic dateMonth/3 as shared. :- dynamic dateYear/3 as shared. :- dynamic description/3 as shared. :- dynamic date/1 as shared. :- dynamic dateInterval/1 as shared. :- dynamic event/1 as shared. :- dynamic location/1 as shared. :- dynamic city/1 as shared. :- dynamic country/1 as shared. :- dynamic region/1 as shared. :- dynamic state/1 as shared. /****************************************************************/ /***************************************************************************** Private predicate definitions ******************************************************************************/ afterP(X,Y,L) :- after(X,Y,L). beforeP(X,Y,L) :- before(X,Y,L). dateAfterP(X,Y,L) :- dateAfter(X,Y,L). dateBeforeP(X,Y,L) :- dateBefore(X,Y,L). intervalAfterP(X,Y,L) :- intervalAfter(X,Y,L). intervalBeforeP(X,Y,L) :- intervalBefore(X,Y,L). differentFromP(X,Y,L) :- differentFrom(X,Y,L). knowsOfP(X,Y,L) :- knowsOf(X,Y,L). relatedPersonOfP(X,Y,L) :- relatedPersonOf(X,Y,L). familyOfP(X,Y,L) :- familyOf(X,Y,L). auntOfP(X,Y,L) :- auntOf(X,Y,L). cousinOfP(X,Y,L) :- cousinOf(X,Y,L). nephewOfP(X,Y,L) :- nephewOf(X,Y,L). nieceOfP(X,Y,L) :- nieceOf(X,Y,L). uncleOfP(X,Y,L) :- uncleOf(X,Y,L). ancestorOfP(X,Y,L) :- ancestorOf(X,Y,L). grandParentOfP(X,Y,L) :- grandParentOf(X,Y,L). grandMotherOfP(X,Y,L) :- grandMotherOf(X,Y,L). grandFatherOfP(X,Y,L) :- grandFatherOf(X,Y,L). parentOfP(X,Y,L) :- parentOf(X,Y,L). fatherOfP(X,Y,L) :- fatherOf(X,Y,L). motherOfP(X,Y,L) :- motherOf(X,Y,L). descendantOfP(X,Y,L) :- descendantOf(X,Y,L). childOfP(X,Y,L) :- childOf(X,Y,L). daughterOfP(X,Y,L) :- daughterOf(X,Y,L). sonOfP(X,Y,L) :- sonOf(X,Y,L). grandChildOfP(X,Y,L) :- grandChildOf(X,Y,L). grandsonOfP(X,Y,L) :- grandsonOf(X,Y,L). granddaughterOfP(X,Y,L) :- granddaughterOf(X,Y,L). inLawOfP(X,Y,L) :- inLawOf(X,Y,L). brotherInLawOfP(X,Y,L) :- brotherInLawOf(X,Y,L). daughterInLawOfP(X,Y,L) :- daughterInLawOf(X,Y,L). fatherInLawOfP(X,Y,L) :- fatherInLawOf(X,Y,L). motherInLawOfP(X,Y,L) :- motherInLawOf(X,Y,L). sisterInLawOfP(X,Y,L) :- sisterInLawOf(X,Y,L). sonInLawOfP(X,Y,L) :- sonInLawOf(X,Y,L). siblingOfP(X,Y,L) :- siblingOf(X,Y,L). brotherOfP(X,Y,L) :- brotherOf(X,Y,L). sisterOfP(X,Y,L) :- sisterOf(X,Y,L). spouseOfP(X,Y,L) :- spouseOf(X,Y,L). husbandOfP(X,Y,L) :- husbandOf(X,Y,L). wifeOfP(X,Y,L) :- wifeOf(X,Y,L). unknownPersonRelationP(X,Y,L) :- unknownPersonRelation(X,Y,L). endsInDateP(X,Y,L) :- endsInDate(X,Y,L). startsInDateP(X,Y,L) :- startsInDate(X,Y,L). expirationDateP(X,Y,L) :- expirationDate(X,Y,L). hasLocationP(X,Y,L) :- hasLocation(X,Y,L). ownedByP(X,Y,L) :- ownedBy(X,Y,L). involvedP(X,Y,L) :- involved(X,Y,L). occursInP(X,Y,L) :- occursIn(X,Y,L). occursDuringP(X,Y,L) :- occursDuring(X,Y,L). operationAreaP(X,Y,L) :- operationArea(X,Y,L). ownerOfP(X,Y,L) :- ownerOf(X,Y,L). relatedEventP(X,Y,L) :- relatedEvent(X,Y,L). teacherP(X,Y,L) :- teacher(X,Y,L). relationObjectP(X,Y,L) :- relationObject(X,Y,L). studentP(X,Y,L) :- student(X,Y,L). ageP(X,Y,L) :- age(X,Y,L). dateDayP(X,Y,L) :- dateDay(X,Y,L). dateMonthP(X,Y,L) :- dateMonth(X,Y,L). dateYearP(X,Y,L) :- dateYear(X,Y,L). descriptionP(X,Y,L) :- description(X,Y,L). dateP(X) :- date(X). dateIntervalP(X) :- dateInterval(X). eventP(X) :- event(X). locationP(X) :- location(X). cityP(X) :- city(X). countryP(X) :- country(X). regionP(X) :- region(X). stateP(X) :- state(X). schoolP(X) :- school(X). personP(X) :- person(X). relationP(X) :- relation(X). directRelationP(X) :- directRelation(X). acquaintanceP(X) :- acquaintance(X). cohabitationP(X) :- cohabitation(X). colleagueshipP(X) :- colleagueship(X). enmityP(X) :- enmity(X). friendshipP(X) :- friendship(X). neighborhoodP(X) :- neighborhood(X). teachingP(X) :- teaching(X). indirectRelationP(X) :- indirectRelation(X). /***************************************************************************** Subproperty rules ******************************************************************************/ relationObjectP(X,Y,L) :- studentP(X,Y,L). relationSubjectP(X,Y,L) :- teacherP(X,Y,L). differentFromP(X,Y,L) :- knowsOfP(X,Y,L). knowsOfP(X,Y,L) :- relatedPersonOfP(X,Y,L). relatedPersonOfP(X,Y,L) :- unknownPersonRelationP(X,Y,L). relatedPersonOfP(X,Y,L) :- familyOfP(X,Y,L). familyOfP(X,Y,L) :- spouseOfP(X,Y,L). spouseOfP(X,Y,L) :- wifeOfP(X,Y,L). spouseOfP(X,Y,L) :- husbandOfP(X,Y,L). familyOfP(X,Y,L) :- siblingOfP(X,Y,L). siblingOfP(X,Y,L) :- sisterOfP(X,Y,L). siblingOfP(X,Y,L) :- brotherOfP(X,Y,L). familyOfP(X,Y,L) :- inLawOfP(X,Y,L). inLawOfP(X,Y,L) :- sonInLawOfP(X,Y,L). inLawOfP(X,Y,L) :- sisterInLawOfP(X,Y,L). inLawOfP(X,Y,L) :- motherInLawOfP(X,Y,L). inLawOfP(X,Y,L) :- fatherInLawOfP(X,Y,L). inLawOfP(X,Y,L) :- daughterInLawOfP(X,Y,L). inLawOfP(X,Y,L) :- brotherInLawOfP(X,Y,L). familyOfP(X,Y,L) :- descendantOfP(X,Y,L). descendantOfP(X,Y,L) :- grandChildOfP(X,Y,L). grandChildOfP(X,Y,L) :- granddaughterOfP(X,Y,L). grandChildOfP(X,Y,L) :- grandsonOfP(X,Y,L). descendantOfP(X,Y,L) :- childOfP(X,Y,L). childOfP(X,Y,L) :- sonOfP(X,Y,L). childOfP(X,Y,L) :- daughterOfP(X,Y,L). familyOfP(X,Y,L) :- ancestorOfP(X,Y,L). ancestorOfP(X,Y,L) :- parentOfP(X,Y,L). parentOfP(X,Y,L) :- motherOfP(X,Y,L). parentOfP(X,Y,L) :- fatherOfP(X,Y,L). ancestorOfP(X,Y,L) :- grandParentOfP(X,Y,L). grandParentOfP(X,Y,L) :- grandFatherOfP(X,Y,L). grandParentOfP(X,Y,L) :- grandMotherOfP(X,Y,L). familyOfP(X,Y,L) :- uncleOfP(X,Y,L). familyOfP(X,Y,L) :- nieceOfP(X,Y,L). familyOfP(X,Y,L) :- nephewOfP(X,Y,L). familyOfP(X,Y,L) :- cousinOfP(X,Y,L). familyOfP(X,Y,L) :- auntOfP(X,Y,L). /***************************************************************************** Symmetry rules ******************************************************************************/ relatedPersonOfP(X,Y,L) :- relatedPersonOfP(Y,X,L). intervalOverlapP(X,Y,L) :- intervalOverlapP(Y,X,L). familyOfP(X,Y,L) :- familyOfP(Y,X,L). cousinOfP(X,Y,L) :- cousinOfP(Y,X,L). siblingOfP(X,Y,L) :- siblingOfP(Y,X,L). spouseOfP(X,Y,L) :- spouseOfP(Y,X,L). /***************************************************************************** Transitivity rules ******************************************************************************/ beforeP(X,Y,L) :- beforeP(X,Z,L1), beforeP(Z,Y,L2), append(L1,L2,L). afterP(X,Y,L) :- afterP(X,Z,L1), afterP(Z,Y,L2), append(L1,L2,L). dateAfterP(X,Y,L) :- dateAfterP(X,Z,L1), dateAfterP(Z,Y,L2), append(L1,L2,L). dateBeforeP(X,Y,L) :- dateBeforeP(X,Z,L1), dateBeforeP(Z,Y,L2), append(L1,L2,L). intervalAfterP(X,Y,L) :- intervalAfterP(X,Z,L1), intervalAfterP(Z,Y,L2), append(L1,L2,L). intervalBeforeP(X,Y,L) :- intervalBeforeP(X,Z,L1), intervalBeforeP(Z,Y,L2), append(L1,L2,L). relatedPersonOfP(X,Y,L) :- relatedPersonOfP(X,Z,L1), relatedPersonOfP(Z,Y,L2), append(L1,L2,L). familyOfP(X,Y,L) :- familyOfP(X,Z,L1), familyOfP(Z,Y,L2), append(L1,L2,L). ancestorOfP(X,Y,L) :- ancestorOfP(X,Z,L1), ancestorOfP(Z,Y,L2), append(L1,L2,L). cousinOfP(X,Y,L) :- cousinOfP(X,Z,L1), cousinOfP(Z,Y,L2), append(L1,L2,L). descendantOfP(X,Y,L) :- descendantOfP(X,Z,L1), descendantOfP(Z,Y,L2), append(L1,L2,L). siblingOfP(X,Y,L) :- siblingOfP(X,Z,L1), siblingOfP(Z,Y,L2), append(L1,L2,L). hasLocationP(X,Y,L) :- hasLocationP(X,Z,L1), hasLocationP(Z,Y,L2), append(L1,L2,L). /***************************************************************************** Inverse rules ******************************************************************************/ beforeP(X,Y,L) :- afterP(Y,X,L). afterP(X,Y,L) :- beforeP(Y,X,L). dateBeforeP(X,Y,L) :- dateAfterP(Y,X,L). dateAfterP(X,Y,L) :- dateBeforeP(Y,X,L). intervalBeforeP(X,Y,L) :- intervalAfterP(Y,X,L). intervalAfterP(X,Y,L) :- intervalBeforeP(Y,X,L). ancestorOfP(X,Y,L) :- descendantOfP(Y,X,L). descendantOfP(X,Y,L) :- ancestorOfP(Y,X,L). childOfP(X,Y,L) :- parentOfP(Y,X,L). parentOfP(X,Y,L) :- childOfP(Y,X,L). grandChildOfP(X,Y,L) :- grandParentOfP(Y,X,L). grandParentOfP(X,Y,L) :- grandChildOfP(Y,X,L). ownedByP(X,Y,L) :- ownerOfP(Y,X,L). ownerOfP(X,Y,L) :- ownedByP(Y,X,L). /***************************************************************************** Property-Chain rules ******************************************************************************/ uncleOfP(X1,X3,L) :- brotherOfP(X1,X2,L1), parentOfP(X2,X3,L2), append(L1,L2,L). uncleOfP(X1,X4,L) :- husbandOfP(X1,X2,L1), sisterOfP(X2,X3,L2), parentOfP(X3,X4,L3), append3(L1,L2,L3,L). parentOfP(X1,X3,L) :- parentOfP(X1,X2,L1), siblingOfP(X2,X3,L2), append(L1,L2,L). nieceOfP(X1,X3,L) :- daughterOfP(X1,X2,L1), siblingOfP(X2,X3,L2), append(L1,L2,L). nephewOfP(X1,X3,L) :- sonOfP(X1,X2,L1), siblingOfP(X2,X3,L2), append(L1,L2,L). sonInLawOfP(X1,X3,L) :- husbandOfP(X1,X2,L1), childOfP(X2,X3,L2), append(L1,L2,L). sisterInLawOfP(X1,X3,L) :- sisterOfP(X1,X2,L1), spouseOfP(X2,X3,L2), append(L1,L2,L). sisterInLawOfP(X1,X3,L) :- wifeOfP(X1,X2,L1), siblingOfP(X2,X3,L2), append(L1,L2,L). motherInLawOfP(X1,X3,L) :- motherOfP(X1,X2,L1), spouseOfP(X2,X3,L2), append(L1,L2,L). fatherInLawOfP(X1,X3,L) :- fatherOfP(X1,X2,L1), spouseOfP(X2,X3,L2), append(L1,L2,L). daughterInLawOfP(X1,X3,L) :- wifeOfP(X1,X2,L1), childOfP(X2,X3,L2), append(L1,L2,L). brotherInLawOfP(X1,X3,L) :- brotherOfP(X1,X2,L1), spouseOfP(X2,X3,L2), append(L1,L2,L). brotherInLawOfP(X1,X3,L) :- husbandOfP(X1,X2,L1), siblingOfP(X2,X3,L2), append(L1,L2,L). grandMotherOfP(X1,X3,L) :- motherOfP(X1,X2,L1), parentOfP(X2,X3,L2), append(L1,L2,L). grandFatherOfP(X1,X3,L) :- fatherOfP(X1,X2,L1), parentOfP(X2,X3,L2), append(L1,L2,L). grandsonOfP(X1,X3,L) :- sonOfP(X1,X2,L1), childOfP(X2,X3,L2), append(L1,L2,L). granddaughterOfP(X1,X3,L) :- daughterOfP(X1,X2,L1), childOfP(X2,X3,L2), append(L1,L2,L). On Aug 21, 2012, at 12:34 PM, David Warren <wa...@cs...> wrote: > abolish_all_private_tables/0 is defined in thread.P, so I guess you need to import it from there. > The manual should say what module a predicate is defined in, and if it doesn't say it's a standard predicate, then it must be imported > > -David > > -----Original Message----- > From: K. A. [mailto:k_a...@ya...] > Sent: Tuesday, August 21, 2012 10:47 AM > To: Xsb...@li...; David Warren; Terrance Swift > Subject: RE: Bug in multi-threaded XSB? > > That's good to hear. After checking with the manual I thought that I would want to call abolish_all_private_tables/0 on a thread poised to answer a query. (This is described on p. 237 of vol. I.) However, when I try that I get: > > "Error: [XSB/Runtime/P]: [Existence (No procedure usermod: > abolish_all_private_tables/0 exists)] []" > > The command-line version doesn't seem to recognize this predicate either. Do I need to import it first from somewhere? > If that doesn't work, what other alternatives are there for destroying private tables? > > Thanks, > > K. > > --- On Tue, 8/21/12, Terrance Swift <ts...@cs...> wrote: > >> From: Terrance Swift <ts...@cs...> >> Subject: RE: Bug in multi-threaded XSB? >> To: "K. A." <k_a...@ya...>, >> "Xsb...@li..." >> <Xsb...@li...>, "David Warren" >> <wa...@cs...> >> Date: Tuesday, August 21, 2012, 8:02 AM Absolutely -- private tables >> are handled just as tables in the single threaded engine, so you can >> abolish them whenever it makes sense in the single threaded engine. >> Heap gc for threads works just as in the single-threaded engine, and >> private dynamic code also works as in the st-engine. >> >> Terry >> >> ________________________________________ >> From: K. A. [k_a...@ya...] >> Sent: Monday, August 20, 2012 10:08 PM >> To: Xsb...@li...; >> David Warren; Terrance Swift >> Subject: RE: Bug in multi-threaded XSB? >> >> Hi Terry, >> >> Thanks for the suggestion. One question: Can a private thread table be >> explicitly abolished on that thread while other threads are running? >> If so, then your suggestion could work with the unkillable threads >> created by xsb_ccall_thread_create - I can maintain a queue of 20 or >> so such threads and reuse them to answer queries, since I can't kill >> them. >> (This would obviously be unworkable in general, but in this case it's >> unlikely that I'll have more than 20 concurrent queries at any given >> time, so it might be viable.) But this presupposes that I can abolish >> their private tables while other threads are running. If not, then I'd >> have to continually spawn new threads to answer new queries, and if >> these threads never quit then I'll be out of memory before too long. >> >> Thanks, >> >> Konstantine >> >> --- On Mon, 8/20/12, Terrance Swift <ts...@cs...> >> wrote: >> >>> From: Terrance Swift <ts...@cs...> >>> Subject: RE: Bug in multi-threaded XSB? >>> To: "K. A." <k_a...@ya...>, >> "Xsb...@li..." >> <Xsb...@li...>, >> "David Warren" <wa...@cs...> >>> Date: Monday, August 20, 2012, 9:34 AM Here is the simple attached >>> file. >>> >>> A couple of people have written large applications >> with >>> MT-XSB but they probably did not use all the features >> you >>> are trying to use, and MT-XSB is certainly less stable >> than >>> single-threaded XSB. I wish I had sufficient time >> to >>> help every user, but looking very briefly at your code, >> its >>> impossible to understand. >>> >>> 1) Why you can't remove the C/XSB interface, at least >> for >>> debugging >>> 2) Why you can't use thread exiting, at least for >> debugging >>> (actually its not an issue from the prolog level, >> threads >>> exit once they have been joined.) >>> 3) How many of the problems in XSB and how many are >>> multi-programming errors of yours. No offense, everybody makes >>> MT-programming errors. >>> >>> I hope you'll take seriously the suggestions I gave you >> to >>> start breaking down the program to help isolate the bugs. I'll try >>> to fix the bugs I can once they >> become >>> clear to me. >>> >>> Terry >>> ________________________________________ >>> From: K. A. [k_a...@ya...] >>> Sent: Sunday, August 19, 2012 7:06 PM >>> To: Xsb...@li...; >>> David Warren; Terrance Swift >>> Subject: RE: Bug in multi-threaded XSB? >>> >>> Hi Terry, >>> >>> Thanks for the reply. >>> >>>> You're absolutely right that sharing tables can (and most probably >>>> would) lead to problems with concurrently executing threads. >>> >>>>> In principle, it shouldn't. In local >>> evaluation, there is a >>>>> mechanism to share concurrently evaluated >> shared >>> tables which >>>>> I think is described in the manual, and is >> described >>> in gory >>>>> detail in Marques and Swift, 2008 ICLP. >>> >>> It shouldn't, as long as there are no insertions while concurrent >>> queries are being answered. But if there are such insertions (as is >>> almost always the case in question-answering systems), then these >>> will not occur with abolished tables but >> rather >>> with whatever tables happen to be in effect at >> insertion >>> time, >>> which will in turn depend on the state of the various active queries >>> at the time. This will most likely invalidate >> the >>> insertions >>> and lead to wrong results. It seems to me that what >> one >>> really >>> needs is the ability to spawn a query at time t with a >>> *fresh* (empty) >>> set of tables and with whatever data happens to be in >> the >>> database at t. I don't know if, with private predicates/tables, >>> there is a way to forcibly copy the contents of one thread's >>> predicates/tables into another. If so, then this could >> be >>> readily implemented in XSB as things stand. But if >> not, >>> then >>> I don't see how XSB's tabling can be used to implement >> a >>> system that does concurrent updates/queries. >>> >>>>> However if you are using MT XSB, I strongly >>> recommend first >>>>> testing out the programming idioms you use from >> the >>> command-line >>>>> shell, then putting things into the C-XSB >>> interface. XSB's >>>>> MT C-Prolog interface is quite ambitious, but >> as a >>> result it >>>>> may have some undiagnosed bugs. Just as >>> importantly, XSB-only >>>>> code will be far, far easier to debug. >>> >>> I'm sure that's the case, but I would think that the >> point >>> of having a C<-->XSB interface is to facilitate >> things >>> that, >>> for some reason or other, cannot be easily done >> exclusively >>> in XSB. If I could program the whole thing in XSB by itself, I >>> could, but I can't. Moreover, it may well be that >> some >>> bugs >>> are peculiar to the C<-->XSB interface and are >> not >>> reproducible >>> when the code is expressed purely in XSB. What happens >> to >>> them? >>> >>>> So I tried declaring >>>> tables to be private, *but* it seems you cannot >> have >>>> shared dynamic predicates with private tables. The predicates >>>> themselves (the facts in the database) >> have >>>> to be "dynamic as shared", because otherwise a new >>> thread >>>> spawned to answer a query would not have any >> usable >>> facts >>>> to work with. But again, the combination "table p/2 >> as >>> private" >>>> with "dynamic p/2 as shared" does not seem to be >> allowed >>> by XSB >>>> (perhaps someone can set me straight if I'm >> missing >>> something). >>> >>>>> I haven't looked at your code, but in principle >> you >>> can do this. >>>>> See the attached file, though I'm sure that >> your >>> program is much >>>>> more complex than the attached file. >>> >>> I didn't see an attached file - could you please >> resend? >>> I'd be very interested to see how this could be done. >>> >>>> At any rate, we're still left with the more narrow >>> question >>>> of why in the world the query threads in this >>> particular >>>> example are not exiting when they are explicitly >>> killed. >>> >>>>> XSB threads should exit when they are killed, >>> although there are cases ?>>where this doesn't happen. For instance >>> if the thread is waiting on >> I/O, >>>>> or waiting on a mutex, etc. the waiting thread >> needs >>> to be signaled, to >>wake up, quit doing whatever >> it >>> is >>>>> doing, and exit. XSB has a lot of OS >>> interfaces, and I haven't yet >>handled this in >> every >>> single case. In addition, when a thread is >> killed >>>>> it must clean up after itself, and free what >> ever >>> mutexes, db_cursors, >>etc. that it has (but may >> not >>> be currently working >>>>> on). While XSB can and does do this for >> some >>> resources, it doesn't >>always have full >> knowledge of >>> all of the resources a thread has taken. >>>> So >>> getting thread cancellation to work in any system is awkward, and >>>>> requires a lot from both the >> system and >>> the user. >>>>> In pretty much any MT system, its better to >> have the >>> thread itself exit, >>and save thread >> cancellation for >>> special cases. >>> >>> Well, these are all special cases unfortunately - >> these >>> threads >>> *never* exit by themselves because for some reason >> which I >>> don't >>> quite understand, they go into a read-eval loop >> *after* >>> they >>> are finished evaluating the goal that they were >> intended >>> to answer. As far as I can see there is no mechanism >> in >>> the C<-->XSB interface to create a thread to do >> a >>> specific >>> job and then quit. The only way to do that would be to execute >>> embedded XSB code using thread_create, but >> then >>> keeping track of the thread id and getting the thread to communicate >>> properly becomes very difficult >> because, >>> again, we are not in XSB proper but in the embedded >> C/XSB >>> world. So xsb_ccall_thread_create seems to be the only viable >>> option, but again, these threads don't quit by >> themselves, >>> so killing them is the only option (and an absolute >> must, >>> because it seems that when multiple threads are >> active, >>> tables cannot be abolished, resources cannot be >> reclaimed, >>> etc.). >>> >>>> So if you can show me how your program works from >> the >>> command-line >interface, I'll help debug at that level. Once we are >>> sure the program is >doing >> what >>> you want at that level, we can see how to add the >> C-XSB >>>> interface. >>> >>> Like I said earlier, this seems to assume that the bug will be >>> reproducible in pure XSB, and I'm not at all sure about that. The C >>> code sample is very small so I hope someone will be able to take a >>> look at it and reach a (tentative, at least) verdict. In the >> meanwhile >>> I'll try to take the client/server I've written in C >> and >>> re-express it in pure XSB using the samples given in >> the >>> /examples/sockets directory of the distribution. Is >> there >>> anyone in particular in this list to whom I should >> direct >>> questions pertaining to that client/server code? >>> >>> Many thanks, >>> >>> Konstantine >>> >>> >>> --- On Sat, 8/18/12, David Warren <wa...@cs...> >>> wrote: >>> >>> >>> >>>> From: David Warren <wa...@cs...> >>> >>>> Subject: RE: Bug in multi-threaded XSB? >>> >>>> To: "K. A." <k_a...@ya...>, >>> "Xsb...@li..." >>> <Xsb...@li...> >>> >>>> Cc: "Terrance Swift" <ts...@cs...> >>> >>>> Date: Saturday, August 18, 2012, 12:17 PM >>> >>>> I strongly suspect it is because you >>> >>>> are sharing the tables and that other thread is >> not >>> exiting >>> >>>> (or at least XSB doesn't know it has exited.) >>> >>>> I would suggest that you don't use shared tables >> but >>> private >>> >>>> tables. If they are not causing this problem now, >> they >>> >>>> certainly will if you run a multithreaded query >>> service >>> >>>> where you have a number of queries and some can >> update >>> the >>> >>>> underlying data. >>> >>>> -David >>> >>>> >>> >>>> -----Original Message----- >>> >>>> From: K. A. [mailto:k_a...@ya...] >>> >>>> >>> >>>> Sent: Friday, August 17, 2012 5:24 PM >>> >>>> To: Xsb...@li... >>> >>>> Cc: David Warren; Terrance Swift >>> >>>> Subject: Bug in multi-threaded XSB? >>> >>>> >>> >>>> Could someone please explain to me why the >> following C >>> code >>> >>>> fails to find any answers to the last query in >> the >>> main >>> >>>> function - the parentOf(X,Y,L) query? >>> >>>> >>> >>>> Note that every insertion does an >> abolish_all_tables >>> first, >>> >>>> and that right before each insertion or query in >> main, >>> there >>> >>>> should be (as far as I can see) only one XSB >> thread >>> active - >>> >>>> the main one. >>> >>>> >>> >>>> I assume this is a bug in multi-threaded XSB >> unless >>> someone >>> >>>> can provide an alternative explanation. >>> >>>> >>> >>>> If you put the C code below in a file test.c, you >> can >>> make >>> >>>> the program as follows: >>> >>>> >>> >>>> gcc -c -I/home/.../XSB/emu >>> >>>> -I/home/.../XSB/config/x86_64-unknown-linux-gnu-mt >> -O3 >>> >>>> -fno-strict-aliasing -Wall -pipe -D_GNU_SOURCE >> test.c >>> >>>> >>> >>>> gcc -o test.out -lm -ldl -Wl -export-dynamic >> -lpthread >>> >>>> >>> >> /home/.../XSB/config/x86_64-unknown-linux-gnu-mt/saved.o/xsb.o >>> >>>> test.o >>> >>>> >>> >>>> #include <stdio.h> >>> >>>> #include <unistd.h> >>> >>>> #include <stdlib.h> >>> >>>> #include <string.h> >>> >>>> #include <sys/types.h> >>> >>>> #include <pthread.h> >>> >>>> #include <ctype.h> >>> >>>> #include "cinterf.h" >>> >>>> #include "varstring_xsb.h" >>> >>>> #include "context.h" >>> >>>> >>> >>>> void doInsert(char* insertion_command,th_context* >> th){ >>> int >>> >>>> res = xsb_command_string(th, >> "abolish_all_tables."); >>> res = >>> >>>> xsb_command_string(th, insertion_command);} >>> >>>> >>> >>>> void doCommand(char* cmd,th_context* th){ int res >> = >>> >>>> xsb_command_string(th, cmd);} >>> >>>> >>> >>>> struct QueryArgs { >>> >>>> char* query; >>> >>>> th_context* th;}; >>> >>>> >>> >>>> void* doQuery(void* args) { >>> >>>> struct QueryArgs * pt = (struct QueryArgs *) >> args; >>> >>>> char* query = (*pt).query; >>> >>>> th_context* th = (*pt).th; >>> >>>> XSB_StrDefine(retstr); >>> >>>> th_context* new_query_thread; >>> >>>> >> xsb_ccall_thread_create(th,&new_query_thread); >>> >>>> int rc = >>> >>>> >>> >> xsb_query_string_string(new_query_thread,query,&retstr,"|"); >>> >>>> int answer_count = 0; >>> >>>> while ((rc == XSB_SUCCESS) && >>> (++answer_count)) >>> >>>> { >>> >>>> printf("\nAnswer: %s\n",retstr.string); >>> >>>> rc = xsb_next_string(new_query_thread, >>> >>>> &retstr,"|"); >>> >>>> } >>> >>>> printf("\n%d answers for this query: >>> >>>> %s\n",answer_count,query); >>> >>>> xsb_kill_thread(new_query_thread); >>> >>>> return NULL;} >>> >>>> >>> >>>> void answerQuery(char* query,th_context* th){ >>> >>>> void* exit_status; >>> >>>> pthread_t new_thread; >>> >>>> struct QueryArgs args = {.query = query, .th = >> th}; >>> >>>> >> pthread_create(&new_thread,NULL,doQuery,(void*) >>> >>>> &args); >>> >>>> pthread_join(new_thread,&exit_status); >>> >>>> } >>> >>>> >>> >>>> int main() { >>> >>>> char init_string[MAXPATHLEN]; >>> >>>> char* xsbHome = getenv("XSB_HOME"); >>> >>>> strcpy(init_string, xsbHome); >>> >>>> xsb_init_string(init_string); >>> >>>> th_context *main_th = xsb_get_main_thread(); >>> >>>> >>> >>>> >>> >> doCommand("consult('prelude.P').",xsb_get_main_thread()); >>> >>>> >>> >> doCommand("load_dyn('main.P').",xsb_get_main_thread()); >>> >>>> >>> >>>> >>> >> doInsert("assert(auntOf(woman9,foo,[])).",xsb_get_main_thread()); >>> >>>> >> answerQuery("familyOf(X,Y,L).",xsb_get_main_thread()); >>> >>>> >>> >>>> >>> >> doInsert("assertAll([parentOf(man2,man3,[1/555]),parentOf(man1,man2,[7 >> /982,1/34])]).",xsb_get_main_thread()); >>> >>>> >> answerQuery("parentOf(X,Y,L).",xsb_get_main_thread()); >>> >>>> xsb_close(xsb_get_main_thread()); >>> >>>> return 0;} >>> >>>> >>> >>>> The contents of the other 2 files are as follows: >>> >>>> >>> >>>> /************* Contents of prelude.P : >>> ***************/ >>> >>>> assertAll([]). >>> >>>> assertAll([H|T]) :- asserta(H),assertAll(T). >>> >>>> >>> >>>> /************* Contents of main.P : >> ***************/ >>> >>>> :- import append/3 from basics. >>> >>>> :- table motherOf/3 as shared. >>> >>>> :- table fatherOf/3 as shared. >>> >>>> :- table parentOf/3 as shared. >>> >>>> :- table ancestorOf/3 as shared. >>> >>>> :- table auntOf/3 as shared. >>> >>>> :- table familyOf/3 as shared. >>> >>>> :- dynamic motherOf/3 as shared. >>> >>>> :- dynamic fatherOf/3 as shared. >>> >>>> :- dynamic parentOf/3 as shared. >>> >>>> :- dynamic ancestorOf/3 as shared. >>> >>>> :- dynamic auntOf/3 as shared. >>> >>>> :- dynamic familyOf/3 as shared. >>> >>>> >>> >>>> familyOf(X,Y,L) :- ancestorOf(X,Y,L). >>> >>>> ancestorOf(X,Y,L) :- parentOf(X,Y,L). >>> >>>> parentOf(X,Y,L) :- motherOf(X,Y,L). >>> >>>> parentOf(X,Y,L) :- fatherOf(X,Y,L). >>> >>>> familyOf(X,Y,L) :- auntOf(X,Y,L). >>> >>>> familyOf(X,Y,L) :- familyOf(Y,X,L). >>> >>>> ancestorOf(X,Y,L) :- ancestorOf(X,Z,L1), >>> ancestorOf(Z,Y,L2), >>> >>>> append(L1,L2,L). >>> >>>> >>> >>>> >>> >>> >>> >>> >>> >>> >>> >> |